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;
89 bool enable_persistent; /* Save the tech state */
93 DBusMessage *pending_reply;
94 guint pending_timeout;
101 bool dbus_registered;
102 #if defined TIZEN_EXT
103 char **enabled_devices;
104 unsigned int mac_policy;
105 unsigned int preassoc_mac_policy;
106 unsigned int random_mac_lifetime;
108 #if defined TIZEN_EXT_WIFI_MESH
109 DBusMessage *mesh_dbus_msg;
113 static GSList *driver_list = NULL;
115 static int technology_enabled(struct connman_technology *technology);
116 static int technology_disabled(struct connman_technology *technology);
118 static gint compare_priority(gconstpointer a, gconstpointer b)
120 const struct connman_technology_driver *driver1 = a;
121 const struct connman_technology_driver *driver2 = b;
123 return driver2->priority - driver1->priority;
126 static void rfkill_check(gpointer key, gpointer value, gpointer user_data)
128 struct connman_rfkill *rfkill = value;
129 enum connman_service_type type = GPOINTER_TO_INT(user_data);
131 /* Calling _technology_add_rfkill will update the tech. */
132 if (rfkill->type == type)
133 __connman_technology_add_rfkill(rfkill->index, type,
134 rfkill->softblock, rfkill->hardblock);
138 connman_technology_is_tethering_allowed(enum connman_service_type type)
140 static char *allowed_default[] = { "wifi", "bluetooth", "gadget",
142 const char *type_str = __connman_service_type2string(type);
149 allowed = connman_setting_get_string_list("TetheringTechnologies");
151 allowed = allowed_default;
153 for (i = 0; allowed[i]; i++) {
154 if (g_strcmp0(allowed[i], type_str) == 0)
161 static const char *get_name(enum connman_service_type type)
164 case CONNMAN_SERVICE_TYPE_UNKNOWN:
165 case CONNMAN_SERVICE_TYPE_SYSTEM:
166 case CONNMAN_SERVICE_TYPE_GPS:
167 case CONNMAN_SERVICE_TYPE_VPN:
169 case CONNMAN_SERVICE_TYPE_GADGET:
171 case CONNMAN_SERVICE_TYPE_ETHERNET:
173 case CONNMAN_SERVICE_TYPE_WIFI:
175 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
177 case CONNMAN_SERVICE_TYPE_CELLULAR:
179 case CONNMAN_SERVICE_TYPE_P2P:
181 #if defined TIZEN_EXT_WIFI_MESH
182 case CONNMAN_SERVICE_TYPE_MESH:
190 static void technology_save(struct connman_technology *technology)
194 const char *name = get_name(technology->type);
196 DBG("technology %p type %d name %s", technology, technology->type,
201 keyfile = __connman_storage_load_global();
203 keyfile = g_key_file_new();
205 identifier = g_strdup_printf("%s", name);
209 g_key_file_set_boolean(keyfile, identifier, "Enable",
210 technology->enable_persistent);
212 g_key_file_set_boolean(keyfile, identifier, "Tethering",
213 technology->tethering_persistent);
215 if (technology->tethering_ident)
216 g_key_file_set_string(keyfile, identifier,
217 "Tethering.Identifier",
218 technology->tethering_ident);
220 if (technology->tethering_passphrase) {
221 char *enc = g_strescape(technology->tethering_passphrase, NULL);
222 g_key_file_set_string(keyfile, identifier,
223 "Tethering.Passphrase", enc);
228 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
229 g_key_file_set_uint64(keyfile, identifier, "MacPolicy",
230 technology->mac_policy);
232 g_key_file_set_uint64(keyfile, identifier, "PreassocMacPolicy",
233 technology->preassoc_mac_policy);
235 g_key_file_set_uint64(keyfile, identifier, "RandomMacLifetime",
236 technology->random_mac_lifetime);
238 #endif /* TIZEN_EXT */
239 if (technology->tethering_freq == 0)
240 technology->tethering_freq = 2412;
242 g_key_file_set_integer(keyfile, identifier,
244 technology->tethering_freq);
249 __connman_storage_save_global(keyfile);
251 g_key_file_free(keyfile);
254 static void tethering_changed(struct connman_technology *technology)
256 dbus_bool_t tethering = technology->tethering;
258 connman_dbus_property_changed_basic(technology->path,
259 CONNMAN_TECHNOLOGY_INTERFACE, "Tethering",
260 DBUS_TYPE_BOOLEAN, &tethering);
262 technology_save(technology);
265 int connman_technology_tethering_notify(struct connman_technology *technology,
270 DBG("technology %p enabled %u", technology, enabled);
272 if (technology->tethering == enabled)
276 err = __connman_tethering_set_enabled();
280 __connman_tethering_set_disabled();
282 technology->tethering = enabled;
283 tethering_changed(technology);
288 static int set_tethering(struct connman_technology *technology,
291 int result = -EOPNOTSUPP;
293 const char *ident, *passphrase, *bridge;
294 GSList *tech_drivers;
296 ident = technology->tethering_ident;
297 passphrase = technology->tethering_passphrase;
299 __sync_synchronize();
300 if (!technology->enabled)
303 bridge = __connman_tethering_get_bridge();
307 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI &&
308 (!ident || !passphrase))
311 for (tech_drivers = technology->driver_list; tech_drivers;
312 tech_drivers = g_slist_next(tech_drivers)) {
313 struct connman_technology_driver *driver = tech_drivers->data;
315 if (!driver || !driver->set_tethering)
318 err = driver->set_tethering(technology, bridge, enabled);
320 if (result == -EINPROGRESS)
323 if (err == -EINPROGRESS || err == 0)
330 void connman_technology_regdom_notify(struct connman_technology *technology,
336 connman_error("Failed to set regulatory domain");
338 DBG("Regulatory domain set to %s", alpha2);
340 g_free(technology->regdom);
341 technology->regdom = g_strdup(alpha2);
344 static int set_regdom_by_device(struct connman_technology *technology,
349 for (list = technology->device_list; list; list = list->next) {
350 struct connman_device *device = list->data;
352 if (connman_device_set_regdom(device, alpha2) != 0)
359 int connman_technology_set_regdom(const char *alpha2)
361 GSList *list, *tech_drivers;
363 for (list = technology_list; list; list = list->next) {
364 struct connman_technology *technology = list->data;
366 if (set_regdom_by_device(technology, alpha2) != 0) {
368 for (tech_drivers = technology->driver_list;
370 tech_drivers = g_slist_next(tech_drivers)) {
372 struct connman_technology_driver *driver =
375 if (driver->set_regdom)
376 driver->set_regdom(technology, alpha2);
384 static struct connman_technology *technology_find(enum connman_service_type type)
388 DBG("type %d", type);
390 for (list = technology_list; list; list = list->next) {
391 struct connman_technology *technology = list->data;
393 if (technology->type == type)
400 enum connman_service_type connman_technology_get_type
401 (struct connman_technology *technology)
404 return CONNMAN_SERVICE_TYPE_UNKNOWN;
406 return technology->type;
409 bool connman_technology_get_wifi_tethering(const struct connman_technology *technology,
410 const char **ssid, const char **psk,
420 /* Workaround for the neard plugin */
422 technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
429 if (!force && !technology->tethering)
432 *ssid = technology->tethering_ident;
433 *psk = technology->tethering_passphrase;
434 *freq = technology->tethering_freq;
439 #if defined TIZEN_EXT
440 const char *connman_techonology_get_path(enum connman_service_type type)
442 struct connman_technology *technology = technology_find(type);
447 return technology->path;
451 static void free_rfkill(gpointer data)
453 struct connman_rfkill *rfkill = data;
458 static void technology_load(struct connman_technology *technology)
462 GError *error = NULL;
463 bool enable, need_saving = false;
470 DBG("technology %p", technology);
472 keyfile = __connman_storage_load_global();
473 /* Fallback on disabling technology if file not found. */
475 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
476 /* We enable ethernet by default */
477 technology->enable_persistent = true;
479 technology->enable_persistent = false;
483 identifier = g_strdup_printf("%s", get_name(technology->type));
489 technology->enabled_devices = g_key_file_get_string_list(keyfile,
490 identifier, "Enable.Devices", &length, NULL);
491 if (technology->enabled_devices && length == 0) {
492 g_strfreev(technology->enabled_devices);
493 technology->enabled_devices = NULL;
497 enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error);
499 technology->enable_persistent = enable;
501 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
502 technology->enable_persistent = true;
504 technology->enable_persistent = false;
507 g_clear_error(&error);
510 enable = g_key_file_get_boolean(keyfile, identifier,
511 "Tethering", &error);
513 technology->tethering_persistent = enable;
516 g_clear_error(&error);
520 technology_save(technology);
522 technology->tethering_ident = g_key_file_get_string(keyfile,
523 identifier, "Tethering.Identifier", NULL);
525 enc = g_key_file_get_string(keyfile,
526 identifier, "Tethering.Passphrase", NULL);
528 technology->tethering_passphrase = g_strcompress(enc);
530 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
531 unsigned int val = 0;
533 val = g_key_file_get_uint64(keyfile,
534 identifier, "MacPolicy", NULL);
536 technology->mac_policy = val;
538 technology->mac_policy = 0;
540 val = g_key_file_get_uint64(keyfile,
541 identifier, "PreassocMacPolicy", NULL);
543 technology->preassoc_mac_policy = val;
545 technology->preassoc_mac_policy = 0;
547 val = g_key_file_get_uint64(keyfile,
548 identifier, "RandomMacLifetime", NULL);
550 technology->random_mac_lifetime = val;
552 technology->random_mac_lifetime = 60;
554 #endif /* TIZEN_EXT */
556 technology->tethering_freq = g_key_file_get_integer(keyfile,
557 identifier, "Tethering.Freq", NULL);
565 g_key_file_free(keyfile);
568 bool __connman_technology_get_offlinemode(void)
570 return global_offlinemode;
573 static void connman_technology_save_offlinemode(void)
576 GError *error = NULL;
579 keyfile = __connman_storage_load_global();
582 keyfile = g_key_file_new();
583 g_key_file_set_boolean(keyfile, "global",
584 "OfflineMode", global_offlinemode);
586 __connman_storage_save_global(keyfile);
589 offlinemode = g_key_file_get_boolean(keyfile, "global",
590 "OfflineMode", &error);
592 if (error || offlinemode != global_offlinemode) {
593 g_key_file_set_boolean(keyfile, "global",
594 "OfflineMode", global_offlinemode);
596 g_clear_error(&error);
598 __connman_storage_save_global(keyfile);
602 g_key_file_free(keyfile);
605 static bool connman_technology_load_offlinemode(void)
608 GError *error = NULL;
611 /* If there is a error, we enable offlinemode */
612 keyfile = __connman_storage_load_global();
616 offlinemode = g_key_file_get_boolean(keyfile, "global",
617 "OfflineMode", &error);
620 g_clear_error(&error);
623 g_key_file_free(keyfile);
628 #if defined TIZEN_EXT
629 static void append_devices(DBusMessageIter *iter, void *user_data)
633 struct connman_technology *technology = user_data;
635 for (list = technology->device_list; list; list = list->next) {
636 struct connman_device *device = list->data;
638 const char *str = connman_device_get_string(device, "Interface");
639 struct connman_network *network = connman_device_get_default_network(device);
640 struct connman_service *service = connman_service_lookup_from_network(network);
642 connman_dbus_dict_append_basic(iter, "Ifname",
643 DBUS_TYPE_STRING, &str);
645 val = connman_device_get_powered(device);
646 connman_dbus_dict_append_basic(iter, "Powered",
647 DBUS_TYPE_BOOLEAN, &val);
649 if (__connman_service_is_connected_state(service, CONNMAN_IPCONFIG_TYPE_IPV4) ||
650 __connman_service_is_connected_state(service, CONNMAN_IPCONFIG_TYPE_IPV6))
655 connman_dbus_dict_append_basic(iter, "Connected",
656 DBUS_TYPE_BOOLEAN, &val);
658 str = connman_device_get_string(device, "Address");
659 connman_dbus_dict_append_basic(iter, "MAC.Address",
660 DBUS_TYPE_STRING, &str);
664 void __connman_technology_append_interfaces(DBusMessageIter *array,
665 enum connman_service_type type, const char *ifname)
668 struct connman_technology *technology = NULL;
670 for (list = technology_list; list; list = list->next) {
671 struct connman_technology *local_tech = list->data;
673 if (local_tech->type != type)
676 technology = local_tech;
683 for (list = technology->device_list; list; list = list->next) {
684 struct connman_device *device = list->data;
685 const char *str = connman_device_get_string(device, "Interface");
687 if (g_strcmp0(ifname, str) == 0)
690 dbus_message_iter_append_basic(array,
691 DBUS_TYPE_STRING, &str);
696 static void append_properties(DBusMessageIter *iter,
697 struct connman_technology *technology)
699 DBusMessageIter dict;
703 connman_dbus_dict_open(iter, &dict);
705 str = get_name(technology->type);
707 connman_dbus_dict_append_basic(&dict, "Name",
708 DBUS_TYPE_STRING, &str);
710 str = __connman_service_type2string(technology->type);
712 connman_dbus_dict_append_basic(&dict, "Type",
713 DBUS_TYPE_STRING, &str);
715 __sync_synchronize();
716 val = technology->enabled;
717 connman_dbus_dict_append_basic(&dict, "Powered",
721 val = technology->connected;
722 connman_dbus_dict_append_basic(&dict, "Connected",
726 val = technology->tethering;
727 connman_dbus_dict_append_basic(&dict, "Tethering",
731 if (technology->tethering_ident)
732 connman_dbus_dict_append_basic(&dict, "TetheringIdentifier",
734 &technology->tethering_ident);
736 if (technology->tethering_passphrase)
737 connman_dbus_dict_append_basic(&dict, "TetheringPassphrase",
739 &technology->tethering_passphrase);
741 #if defined TIZEN_EXT
742 connman_dbus_dict_append_basic(&dict, "MacPolicy",
744 &(technology->mac_policy));
746 connman_dbus_dict_append_basic(&dict, "PreassocMacPolicy",
748 &(technology->preassoc_mac_policy));
750 connman_dbus_dict_append_basic(&dict, "RandomMacLifetime",
752 &(technology->random_mac_lifetime));
754 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI)
755 connman_dbus_dict_append_dict(&dict, "Device.List",
756 append_devices, technology);
757 if (technology->regdom)
758 connman_dbus_dict_append_basic(&dict, "CountryCode",
760 &technology->regdom);
762 connman_dbus_dict_append_basic(&dict, "TetheringFreq",
764 &technology->tethering_freq);
765 connman_dbus_dict_close(iter, &dict);
768 static void technology_added_signal(struct connman_technology *technology)
771 DBusMessageIter iter;
773 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
774 CONNMAN_MANAGER_INTERFACE, "TechnologyAdded");
778 dbus_message_iter_init_append(signal, &iter);
779 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
781 append_properties(&iter, technology);
783 dbus_connection_send(connection, signal, NULL);
784 dbus_message_unref(signal);
787 static void technology_removed_signal(struct connman_technology *technology)
789 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
790 CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
791 DBUS_TYPE_OBJECT_PATH, &technology->path,
795 static DBusMessage *get_properties(DBusConnection *conn,
796 DBusMessage *message, void *user_data)
798 struct connman_technology *technology = user_data;
800 DBusMessageIter iter;
802 reply = dbus_message_new_method_return(message);
806 dbus_message_iter_init_append(reply, &iter);
807 append_properties(&iter, technology);
812 void __connman_technology_list_struct(DBusMessageIter *array)
815 DBusMessageIter entry;
817 for (list = technology_list; list; list = list->next) {
818 struct connman_technology *technology = list->data;
820 if (!technology->path ||
821 (technology->rfkill_driven &&
822 technology->hardblocked))
825 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
827 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
829 append_properties(&entry, technology);
830 dbus_message_iter_close_container(array, &entry);
834 static gboolean technology_pending_reply(gpointer user_data)
836 struct connman_technology *technology = user_data;
839 /* Power request timed out, send ETIMEDOUT. */
840 if (technology->pending_reply) {
841 reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
843 g_dbus_send_message(connection, reply);
845 dbus_message_unref(technology->pending_reply);
846 technology->pending_reply = NULL;
847 technology->pending_timeout = 0;
853 static int technology_affect_devices(struct connman_technology *technology,
856 int err = 0, err_dev;
859 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
861 __connman_technology_enabled(technology->type);
863 __connman_technology_disabled(technology->type);
867 #if defined TIZEN_EXT_WIFI_MESH
868 if (technology->type == CONNMAN_SERVICE_TYPE_MESH)
872 for (list = technology->device_list; list; list = list->next) {
873 struct connman_device *device = list->data;
876 err_dev = __connman_device_enable(device);
878 err_dev = __connman_device_disable(device);
880 if (err_dev < 0 && err_dev != -EALREADY)
887 static void powered_changed(struct connman_technology *technology)
891 if (!technology->dbus_registered)
894 if (technology->pending_reply) {
895 g_dbus_send_reply(connection,
896 technology->pending_reply, DBUS_TYPE_INVALID);
897 dbus_message_unref(technology->pending_reply);
898 technology->pending_reply = NULL;
900 g_source_remove(technology->pending_timeout);
901 technology->pending_timeout = 0;
904 __sync_synchronize();
905 enabled = technology->enabled;
906 #if defined TIZEN_EXT
907 DBG("ConnMan, Powered : %s, %s",
908 enabled ? "TRUE" : "FALSE",technology->path);
910 connman_dbus_property_changed_basic(technology->path,
911 CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
912 DBUS_TYPE_BOOLEAN, &enabled);
915 static void enable_tethering(struct connman_technology *technology)
919 if (!connman_setting_get_bool("PersistentTetheringMode"))
922 ret = set_tethering(technology, true);
923 if (ret < 0 && ret != -EALREADY)
924 DBG("Cannot enable tethering yet for %s (%d/%s)",
925 get_name(technology->type),
926 -ret, strerror(-ret));
929 static int technology_enabled(struct connman_technology *technology)
931 __sync_synchronize();
932 if (technology->enabled)
935 technology->enabled = true;
937 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
938 struct connman_technology *p2p;
940 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
941 if (p2p && !p2p->enabled && p2p->enable_persistent)
942 technology_enabled(p2p);
945 if (technology->tethering_persistent)
946 enable_tethering(technology);
948 powered_changed(technology);
953 static int technology_enable(struct connman_technology *technology)
958 DBG("technology %p enable", technology);
960 __sync_synchronize();
962 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
963 struct connman_technology *wifi;
965 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
966 if (wifi && wifi->enabled)
967 return technology_enabled(technology);
971 if (technology->enabled)
974 if (technology->pending_reply)
977 if (connman_setting_get_bool("PersistentTetheringMode") &&
978 technology->tethering)
979 set_tethering(technology, true);
981 if (technology->rfkill_driven)
982 err = __connman_rfkill_block(technology->type, false);
984 err_dev = technology_affect_devices(technology, true);
986 if (!technology->rfkill_driven)
992 static int technology_disabled(struct connman_technology *technology)
994 __sync_synchronize();
995 if (!technology->enabled)
998 technology->enabled = false;
1000 powered_changed(technology);
1005 static int technology_disable(struct connman_technology *technology)
1009 DBG("technology %p disable", technology);
1011 __sync_synchronize();
1013 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
1014 technology->enable_persistent = false;
1015 __connman_device_stop_scan(CONNMAN_SERVICE_TYPE_P2P);
1016 __connman_peer_disconnect_all();
1017 return technology_disabled(technology);
1018 } else if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
1019 struct connman_technology *p2p;
1021 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
1022 if (p2p && p2p->enabled) {
1023 p2p->enable_persistent = true;
1024 technology_disabled(p2p);
1028 if (!technology->enabled)
1031 if (technology->pending_reply)
1034 if (technology->tethering)
1035 set_tethering(technology, false);
1037 err = technology_affect_devices(technology, false);
1039 if (technology->rfkill_driven)
1040 err = __connman_rfkill_block(technology->type, true);
1045 static DBusMessage *set_powered(struct connman_technology *technology,
1046 DBusMessage *msg, bool powered)
1048 DBusMessage *reply = NULL;
1051 if (technology->rfkill_driven && technology->hardblocked) {
1057 err = technology_enable(technology);
1059 err = technology_disable(technology);
1061 if (err != -EBUSY) {
1062 technology->enable_persistent = powered;
1063 technology_save(technology);
1067 if (err == -EINPROGRESS) {
1068 technology->pending_reply = dbus_message_ref(msg);
1069 technology->pending_timeout = g_timeout_add_seconds(10,
1070 technology_pending_reply, technology);
1071 } else if (err == -EALREADY) {
1073 reply = __connman_error_already_enabled(msg);
1075 reply = __connman_error_already_disabled(msg);
1077 reply = __connman_error_failed(msg, -err);
1079 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1084 #if defined TIZEN_EXT
1085 int set_connman_bssid(enum bssid_type mode, char *bssid, const char *ifname)
1087 static int bssid_len;
1088 static const char *def_ifname = "default";
1089 static GSList *bssid_list = NULL;
1091 const char *local_ifname = ifname;
1093 struct connman_bssid_pending *bssid_info;
1095 DBG("mode: %d, ifname: %s", mode, ifname);
1098 local_ifname = def_ifname;
1100 for (list = bssid_list; list; list = list->next) {
1101 bssid_info = list->data;
1103 if (g_strcmp0(bssid_info->ifname, local_ifname) == 0) {
1109 if (mode == CHECK_BSSID) {
1116 if (mode == GET_BSSID && bssid) {
1118 memcpy(bssid, bssid_info->bssid, 6);
1124 if (mode == RESET_BSSID) {
1126 bssid_list = g_slist_remove(bssid_list, bssid_info);
1127 g_free(bssid_info->ifname);
1133 if (mode != SET_BSSID || !bssid) {
1134 DBG("Invalid parameter");
1139 bssid_list = g_slist_remove(bssid_list, bssid_info);
1140 g_free(bssid_info->ifname);
1144 bssid_info = g_try_malloc0(sizeof(struct connman_bssid_pending));
1146 DBG("Failed to allocate memory");
1150 unsigned char *bssid_data = bssid_info->bssid;
1152 bssid_len = sscanf(bssid, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1153 &bssid_data[0], &bssid_data[1], &bssid_data[2],
1154 &bssid_data[3], &bssid_data[4], &bssid_data[5]);
1155 if (bssid_len != 6) {
1156 DBG("Incorrect BSSID format. bssid_len = %d", bssid_len);
1161 DBG("SET BSSID len: %d, BSSID: %02x:%02x:%02x:%02x:%02x:%02x ifname: %s",
1163 bssid_data[0], bssid_data[1], bssid_data[2],
1164 bssid_data[3], bssid_data[4], bssid_data[5],
1167 bssid_info->ifname = g_strdup(ifname);
1168 bssid_list = g_slist_prepend(bssid_list, bssid_info);
1173 void connman_technology_mac_policy_notify(struct connman_technology *technology,
1174 unsigned int policy)
1176 DBG("Mac polict set to %u", policy);
1178 technology->mac_policy = policy;
1179 technology_save(technology);
1182 void __connman_technology_notify_mac_policy_by_device(struct connman_device *device,
1183 int result, unsigned int policy)
1185 struct connman_technology *technology;
1186 enum connman_service_type type;
1188 type = __connman_device_get_service_type(device);
1189 technology = technology_find(type);
1194 connman_technology_mac_policy_notify(technology, policy);
1197 static DBusMessage *set_mac_policy(struct connman_technology *technology,
1198 DBusMessage *msg, unsigned int policy)
1200 DBusMessage *reply = NULL;
1202 unsigned int last_policy = technology->mac_policy;
1204 if (technology->rfkill_driven && technology->hardblocked) {
1209 for (GSList *list = technology->device_list; list; list = list->next) {
1210 struct connman_device *device = list->data;
1212 err = connman_device_set_mac_policy(device, policy);
1219 if (err != -EACCES && err != -EOPNOTSUPP) {
1220 for (GSList *list = technology->device_list; list; list = list->next) {
1221 struct connman_device *device = list->data;
1223 connman_device_set_mac_policy(device, last_policy);
1227 reply = __connman_error_failed(msg, -err);
1229 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1235 void connman_technology_preassoc_mac_policy_notify(struct connman_technology *technology,
1236 unsigned int policy)
1238 DBG("Preassoc mac polict set to %u", policy);
1240 technology->preassoc_mac_policy = policy;
1241 technology_save(technology);
1244 void __connman_technology_notify_preassoc_mac_policy_by_device(struct connman_device *device,
1245 int result, unsigned int policy)
1247 struct connman_technology *technology;
1248 enum connman_service_type type;
1250 type = __connman_device_get_service_type(device);
1251 technology = technology_find(type);
1256 connman_technology_preassoc_mac_policy_notify(technology, policy);
1259 static DBusMessage *set_preassoc_mac_policy(struct connman_technology *technology,
1260 DBusMessage *msg, unsigned int policy)
1262 DBusMessage *reply = NULL;
1264 unsigned int last_policy = technology->preassoc_mac_policy;
1266 if (technology->rfkill_driven && technology->hardblocked) {
1271 for (GSList *list = technology->device_list; list; list = list->next) {
1272 struct connman_device *device = list->data;
1274 err = connman_device_set_preassoc_mac_policy(device, policy);
1281 if (err != -EACCES && err != -EOPNOTSUPP) {
1282 for (GSList *list = technology->device_list; list; list = list->next) {
1283 struct connman_device *device = list->data;
1285 connman_device_set_preassoc_mac_policy(device, last_policy);
1289 reply = __connman_error_failed(msg, -err);
1291 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1297 void connman_technology_random_mac_lifetime_notify(struct connman_technology *technology,
1298 unsigned int lifetime)
1300 DBG("Random mac lifetime set to %u", lifetime);
1302 technology->random_mac_lifetime = lifetime;
1303 technology_save(technology);
1306 void __connman_technology_notify_random_mac_lifetime_by_device(struct connman_device *device,
1307 int result, unsigned int lifetime)
1309 struct connman_technology *technology;
1310 enum connman_service_type type;
1312 type = __connman_device_get_service_type(device);
1313 technology = technology_find(type);
1318 connman_technology_random_mac_lifetime_notify(technology, lifetime);
1321 static DBusMessage *set_random_mac_lifetime(struct connman_technology *technology,
1322 DBusMessage *msg, unsigned int lifetime)
1324 DBusMessage *reply = NULL;
1326 unsigned int last_lifetime = technology->random_mac_lifetime;
1328 if (technology->rfkill_driven && technology->hardblocked) {
1333 for (GSList *list = technology->device_list; list; list = list->next) {
1334 struct connman_device *device = list->data;
1336 err = connman_device_set_random_mac_lifetime(device, lifetime);
1341 if (err != -EACCES && err != -EOPNOTSUPP) {
1342 for (GSList *list = technology->device_list; list; list = list->next) {
1343 struct connman_device *device = list->data;
1345 connman_device_set_random_mac_lifetime(device, last_lifetime);
1349 reply = __connman_error_failed(msg, -err);
1351 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1358 static DBusMessage *set_property(DBusConnection *conn,
1359 DBusMessage *msg, void *data)
1361 struct connman_technology *technology = data;
1362 DBusMessageIter iter, value;
1366 DBG("conn %p", conn);
1368 if (!dbus_message_iter_init(msg, &iter))
1369 return __connman_error_invalid_arguments(msg);
1371 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1372 return __connman_error_invalid_arguments(msg);
1374 dbus_message_iter_get_basic(&iter, &name);
1375 dbus_message_iter_next(&iter);
1377 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1378 return __connman_error_invalid_arguments(msg);
1380 dbus_message_iter_recurse(&iter, &value);
1382 type = dbus_message_iter_get_arg_type(&value);
1384 DBG("property %s", name);
1386 if (g_str_equal(name, "Tethering")) {
1387 dbus_bool_t tethering;
1390 if (type != DBUS_TYPE_BOOLEAN)
1391 return __connman_error_invalid_arguments(msg);
1393 if (!connman_technology_is_tethering_allowed(technology->type)) {
1394 DBG("%s tethering not allowed by config file",
1395 __connman_service_type2string(technology->type));
1396 return __connman_error_not_supported(msg);
1399 dbus_message_iter_get_basic(&value, &tethering);
1401 if (technology->tethering == tethering) {
1403 return __connman_error_already_disabled(msg);
1405 return __connman_error_already_enabled(msg);
1408 err = set_tethering(technology, tethering);
1410 return __connman_error_failed(msg, -err);
1412 technology->tethering_persistent = tethering;
1414 technology_save(technology);
1416 } else if (g_str_equal(name, "TetheringIdentifier")) {
1419 dbus_message_iter_get_basic(&value, &str);
1421 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1422 return __connman_error_not_supported(msg);
1424 if (strlen(str) < 1 || strlen(str) > 32)
1425 return __connman_error_invalid_arguments(msg);
1427 if (g_strcmp0(technology->tethering_ident, str) != 0) {
1428 g_free(technology->tethering_ident);
1429 technology->tethering_ident = g_strdup(str);
1430 technology_save(technology);
1432 connman_dbus_property_changed_basic(technology->path,
1433 CONNMAN_TECHNOLOGY_INTERFACE,
1434 "TetheringIdentifier",
1436 &technology->tethering_ident);
1438 } else if (g_str_equal(name, "TetheringPassphrase")) {
1441 dbus_message_iter_get_basic(&value, &str);
1443 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1444 return __connman_error_not_supported(msg);
1446 err = __connman_service_check_passphrase(CONNMAN_SERVICE_SECURITY_PSK,
1449 return __connman_error_passphrase_required(msg);
1451 if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
1452 g_free(technology->tethering_passphrase);
1453 technology->tethering_passphrase = g_strdup(str);
1454 technology_save(technology);
1456 connman_dbus_property_changed_basic(technology->path,
1457 CONNMAN_TECHNOLOGY_INTERFACE,
1458 "TetheringPassphrase",
1460 &technology->tethering_passphrase);
1462 } else if (g_str_equal(name, "TetheringFreq")) {
1465 if (type != DBUS_TYPE_INT32)
1466 return __connman_error_invalid_arguments(msg);
1468 dbus_message_iter_get_basic(&value, &freq);
1470 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1471 return __connman_error_not_supported(msg);
1474 technology->tethering_freq = freq;
1475 technology_save(technology);
1477 connman_dbus_property_changed_basic(technology->path,
1478 CONNMAN_TECHNOLOGY_INTERFACE,
1481 &technology->tethering_freq);
1483 } else if (g_str_equal(name, "Powered")) {
1486 if (type != DBUS_TYPE_BOOLEAN)
1487 return __connman_error_invalid_arguments(msg);
1489 dbus_message_iter_get_basic(&value, &enable);
1491 return set_powered(technology, msg, enable);
1492 #if defined TIZEN_EXT
1493 } else if (g_str_equal(name, "SetBSSID")) {
1496 if (type != DBUS_TYPE_STRING)
1497 return __connman_error_invalid_arguments(msg);
1499 dbus_message_iter_get_basic(&value, &key);
1500 DBG("BSSID %s", key);
1501 set_connman_bssid(SET_BSSID, key, NULL);
1502 } else if (g_str_equal(name, "MacPolicy")) {
1503 dbus_uint32_t mac_policy;
1505 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1506 return __connman_error_not_supported(msg);
1508 if (type != DBUS_TYPE_UINT32)
1509 return __connman_error_invalid_arguments(msg);
1511 dbus_message_iter_get_basic(&value, &mac_policy);
1513 if (mac_policy <= 2)
1514 return set_mac_policy(technology, msg, mac_policy);
1516 return __connman_error_invalid_arguments(msg);
1518 } else if (g_str_equal(name, "PreassocMacPolicy")) {
1519 dbus_uint32_t preassoc_mac_policy;
1521 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1522 return __connman_error_not_supported(msg);
1524 if (type != DBUS_TYPE_UINT32)
1525 return __connman_error_invalid_arguments(msg);
1527 dbus_message_iter_get_basic(&value, &preassoc_mac_policy);
1529 if (preassoc_mac_policy <= 2)
1530 return set_preassoc_mac_policy(technology, msg, preassoc_mac_policy);
1532 return __connman_error_invalid_arguments(msg);
1534 } else if (g_str_equal(name, "RandomMacLifetime")) {
1535 dbus_uint32_t random_mac_lifetime;
1537 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1538 return __connman_error_not_supported(msg);
1540 if (type != DBUS_TYPE_UINT32)
1541 return __connman_error_invalid_arguments(msg);
1543 dbus_message_iter_get_basic(&value, &random_mac_lifetime);
1545 if (random_mac_lifetime > 0)
1546 return set_random_mac_lifetime(technology, msg, random_mac_lifetime);
1548 return __connman_error_invalid_arguments(msg);
1550 } else if (g_str_equal(name, "CountryCode")) {
1553 dbus_message_iter_get_basic(&value, &str);
1554 DBG("country code %s", str);
1555 connman_technology_set_regdom(str);
1558 return __connman_error_invalid_property(msg);
1560 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1563 static void reply_scan_pending(struct connman_technology *technology, int err)
1567 DBG("technology %p err %d", technology, err);
1569 while (technology->scan_pending) {
1570 #if defined TIZEN_EXT
1571 struct connman_scan_pending *pending_data = technology->scan_pending->data;
1572 DBusMessage *msg = pending_data->msg;
1574 DBusMessage *msg = technology->scan_pending->data;
1576 DBG("reply to %s", dbus_message_get_sender(msg));
1579 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1581 reply = __connman_error_failed(msg, -err);
1582 g_dbus_send_message(connection, reply);
1583 dbus_message_unref(msg);
1585 technology->scan_pending =
1586 g_slist_delete_link(technology->scan_pending,
1587 technology->scan_pending);
1588 #if defined TIZEN_EXT
1589 g_free(pending_data->ifname);
1590 g_free(pending_data);
1595 #if defined TIZEN_EXT
1596 dbus_bool_t __connman_technology_notify_scan_changed(const char *key, void *val)
1599 DBusMessage *signal;
1600 DBusMessageIter iter;
1601 dbus_bool_t result = FALSE;
1603 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1604 CONNMAN_MANAGER_INTERFACE, "ScanChanged");
1608 dbus_message_iter_init_append(signal, &iter);
1610 connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_BOOLEAN, val);
1612 connman_dbus_property_append_basic(&iter, "", DBUS_TYPE_BOOLEAN, val);
1614 result = dbus_connection_send(connection, signal, NULL);
1615 dbus_message_unref(signal);
1617 DBG("Successfuly sent signal");
1622 void __connman_technology_notify_scan_done(const char *ifname, int val)
1625 DBusMessage *signal;
1626 DBusMessageIter iter;
1628 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1629 CONNMAN_MANAGER_INTERFACE, "ScanDone");
1633 dbus_message_iter_init_append(signal, &iter);
1635 connman_dbus_property_append_basic(&iter, ifname,
1636 DBUS_TYPE_INT32, &val);
1638 connman_dbus_property_append_basic(&iter, "",
1639 DBUS_TYPE_INT32, &val);
1641 dbus_connection_send(connection, signal, NULL);
1642 dbus_message_unref(signal);
1644 DBG("Successfuly sent ScanDone signal");
1647 static void reply_scan_pending_device(
1648 struct connman_technology *technology, const char *ifname, int count)
1652 dbus_bool_t status = 0;
1653 connman_scan_type_e scan_type = CONNMAN_SCAN_TYPE_UNKNOWN;
1655 DBG("technology %p ifname %s count %d", technology, ifname, count);
1657 list = technology->scan_pending;
1660 struct connman_scan_pending *pending_data = list->data;
1661 DBusMessage *msg = pending_data->msg;
1664 if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN)
1665 scan_type = pending_data->scan_type;
1667 if (count != 0 && g_strcmp0(pending_data->ifname, ifname) != 0)
1670 scan_type = pending_data->scan_type;
1672 DBG("reply to %s", dbus_message_get_sender(msg));
1673 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1675 g_dbus_send_message(connection, reply);
1676 dbus_message_unref(msg);
1678 technology->scan_pending =
1679 g_slist_remove(technology->scan_pending, pending_data);
1681 g_free(pending_data->ifname);
1682 g_free(pending_data);
1685 if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN)
1686 scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1688 __connman_technology_notify_scan_changed(ifname, &status);
1689 __connman_technology_notify_scan_done(ifname, scan_type);
1692 static void __connman_technology_notify_device_detected(
1693 struct connman_technology *technology, const char *ifname, bool val)
1696 DBusMessage *signal;
1697 DBusMessageIter iter;
1698 dbus_bool_t detected = val;
1703 signal = dbus_message_new_signal(technology->path,
1704 CONNMAN_TECHNOLOGY_INTERFACE, "DeviceDetected");
1708 dbus_message_iter_init_append(signal, &iter);
1709 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ifname);
1710 dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &detected);
1712 dbus_connection_send(connection, signal, NULL);
1713 dbus_message_unref(signal);
1715 DBG("Successfuly sent DeviceDetected signal");
1718 void __connman_technology_notify_device_detected_by_device(
1719 struct connman_device *device, const char *ifname, bool val)
1721 struct connman_technology *technology;
1722 enum connman_service_type type;
1724 type = __connman_device_get_service_type(device);
1726 technology = technology_find(type);
1728 __connman_technology_notify_device_detected(technology, ifname, val);
1731 void __connman_technology_notify_roaming_state(const char *ifname,
1732 const char *state, const char *cur_bssid, const char *dst_bssid)
1735 DBusMessage *signal;
1736 DBusMessageIter array, dict;
1738 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1739 CONNMAN_MANAGER_INTERFACE, "RoamingStateChanged");
1743 dbus_message_iter_init_append(signal, &array);
1745 connman_dbus_dict_open(&array, &dict);
1748 connman_dbus_dict_append_basic(&dict, "Interface",
1749 DBUS_TYPE_STRING, &ifname);
1751 connman_dbus_dict_append_basic(&dict, "State",
1752 DBUS_TYPE_STRING, &state);
1754 connman_dbus_dict_append_basic(&dict, "ConnectedBSSID",
1755 DBUS_TYPE_STRING, &cur_bssid);
1757 connman_dbus_dict_append_basic(&dict, "TargetBSSID",
1758 DBUS_TYPE_STRING, &dst_bssid);
1760 connman_dbus_dict_close(&array, &dict);
1762 dbus_connection_send(connection, signal, NULL);
1763 dbus_message_unref(signal);
1765 DBG("Successfully sent Roaming State Changed signal");
1769 void __connman_technology_scan_started(struct connman_device *device)
1771 DBG("device %p", device);
1772 #if defined TIZEN_EXT
1773 dbus_bool_t status = 1;
1774 const char *ifname = connman_device_get_string(device, "Interface");
1776 __connman_technology_notify_scan_changed(ifname, &status);
1780 void __connman_technology_scan_stopped(struct connman_device *device,
1781 enum connman_service_type type)
1784 struct connman_technology *technology;
1787 technology = technology_find(type);
1789 DBG("technology %p device %p", technology, device);
1794 for (list = technology->device_list; list; list = list->next) {
1795 struct connman_device *other_device = list->data;
1797 if (device == other_device)
1800 if (connman_device_get_scanning(other_device, type))
1804 #if defined TIZEN_EXT
1805 const char *ifname = connman_device_get_string(device, "Interface");
1806 reply_scan_pending_device(technology, ifname, count);
1811 reply_scan_pending(technology, 0);
1815 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
1816 int result, const char *alpha2)
1818 bool regdom_set = false;
1819 struct connman_technology *technology;
1820 enum connman_service_type type;
1821 GSList *tech_drivers;
1823 type = __connman_device_get_service_type(device);
1824 technology = technology_find(type);
1831 for (tech_drivers = technology->driver_list;
1833 tech_drivers = g_slist_next(tech_drivers)) {
1834 struct connman_technology_driver *driver =
1837 if (driver->set_regdom) {
1838 driver->set_regdom(technology, alpha2);
1848 connman_technology_regdom_notify(technology, alpha2);
1851 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
1853 struct connman_technology *technology = data;
1856 DBG("technology %p request from %s", technology,
1857 dbus_message_get_sender(msg));
1859 if (technology->type == CONNMAN_SERVICE_TYPE_P2P &&
1860 !technology->enabled)
1861 return __connman_error_permission_denied(msg);
1863 #if !defined TIZEN_EXT
1864 dbus_message_ref(msg);
1865 technology->scan_pending =
1866 g_slist_prepend(technology->scan_pending, msg);
1869 err = __connman_device_request_scan_full(technology->type);
1871 #if defined TIZEN_EXT
1872 return __connman_error_failed(msg, -err);
1874 reply_scan_pending(technology, err);
1877 #if defined TIZEN_EXT
1878 struct connman_scan_pending *pending_data =
1879 g_try_malloc0(sizeof(struct connman_scan_pending));
1881 return __connman_error_failed(msg, ENOMEM);
1883 pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1884 DBG("scan_type %d", pending_data->scan_type);
1886 pending_data->msg = dbus_message_ref(msg);
1888 technology->scan_pending =
1889 g_slist_prepend(technology->scan_pending, pending_data);
1894 #if defined TIZEN_EXT
1895 static DBusMessage *scan_device(DBusConnection *conn, DBusMessage *msg, void *data)
1897 struct connman_technology *technology = data;
1898 DBusMessageIter iter;
1902 DBG("technology %p request from %s", technology,
1903 dbus_message_get_sender(msg));
1905 if (!dbus_message_iter_init(msg, &iter))
1906 return __connman_error_invalid_arguments(msg);
1908 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1909 return __connman_error_invalid_arguments(msg);
1911 dbus_message_iter_get_basic(&iter, &ifname);
1912 DBG("Interface name %s", ifname);
1914 if (!ifname || strlen(ifname) == 0)
1915 return __connman_error_invalid_arguments(msg);
1917 err = connman_device_request_device_scan(technology->type, ifname, true);
1919 return __connman_error_failed(msg, -err);
1921 struct connman_scan_pending *pending_data =
1922 g_try_malloc0(sizeof(struct connman_scan_pending));
1924 return __connman_error_failed(msg, ENOMEM);
1926 pending_data->ifname = g_strdup(ifname);
1927 if (pending_data->ifname == NULL) {
1928 g_free(pending_data);
1929 return __connman_error_failed(msg, ENOMEM);
1932 pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1933 DBG("scan_type %d", pending_data->scan_type);
1935 pending_data->msg = dbus_message_ref(msg);
1937 technology->scan_pending =
1938 g_slist_prepend(technology->scan_pending, pending_data);
1943 static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void *data)
1945 struct connman_technology *technology = data;
1946 GSList *specific_scan_list = NULL;
1948 const char *name = NULL;
1949 const char *freq = NULL;
1950 const char *ifname = NULL;
1951 DBusMessageIter iter, dict;
1954 DBG("technology %p request from %s", technology,
1955 dbus_message_get_sender(msg));
1957 if (!dbus_message_iter_init(msg, &iter))
1958 return __connman_error_invalid_arguments(msg);
1960 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1961 return __connman_error_invalid_arguments(msg);
1963 dbus_message_iter_recurse(&iter, &dict);
1964 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1965 DBusMessageIter entry, value2;
1969 dbus_message_iter_recurse(&dict, &entry);
1970 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) {
1971 g_slist_free_full(specific_scan_list, g_free);
1972 return __connman_error_invalid_arguments(msg);
1975 dbus_message_iter_get_basic(&entry, &key);
1976 dbus_message_iter_next(&entry);
1978 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) {
1979 g_slist_free_full(specific_scan_list, g_free);
1980 return __connman_error_invalid_arguments(msg);
1983 dbus_message_iter_recurse(&entry, &value2);
1984 type = dbus_message_iter_get_arg_type(&value2);
1985 if (g_str_equal(key, "Ifname") && type == DBUS_TYPE_STRING) {
1987 dbus_message_iter_get_basic(&value2, &ifname);
1988 DBG("ifname %s", ifname);
1989 } else if (g_str_equal(key, "SSID")) {
1990 if (type != DBUS_TYPE_STRING) {
1991 g_slist_free_full(specific_scan_list, g_free);
1992 return __connman_error_invalid_arguments(msg);
1995 scan_type = CONNMAN_MULTI_SCAN_SSID; /* SSID based scan */
1996 dbus_message_iter_get_basic(&value2, &name);
1997 DBG("name %s", name);
1998 specific_scan_list = g_slist_append(specific_scan_list, g_strdup(name));
1999 } else if (g_str_equal(key, "Frequency")) {
2000 if (type != DBUS_TYPE_STRING) {
2001 g_slist_free_full(specific_scan_list, g_free);
2002 return __connman_error_invalid_arguments(msg);
2005 scan_type = CONNMAN_MULTI_SCAN_FREQ; /* Frequency based scan */
2006 dbus_message_iter_get_basic(&value2, &freq);
2007 DBG("freq %s", freq);
2008 specific_scan_list = g_slist_append(specific_scan_list, GINT_TO_POINTER(atoi(freq)));
2009 } else if (g_str_equal(key, "SSID_Mixed")) {
2010 if (type != DBUS_TYPE_STRING) {
2011 g_slist_free_full(specific_scan_list, g_free);
2012 return __connman_error_invalid_arguments(msg);
2015 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
2016 dbus_message_iter_get_basic(&value2, &name);
2018 connman_multi_scan_ap_s *ap =
2019 (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
2021 g_strlcpy(ap->str, name, strlen(name) + 1);
2023 specific_scan_list = g_slist_append(specific_scan_list, ap);
2025 DBG("Failed to allocate memory");
2027 } else if (g_str_equal(key, "Frequency_Mixed")) {
2028 if (type != DBUS_TYPE_STRING) {
2029 g_slist_free_full(specific_scan_list, g_free);
2030 return __connman_error_invalid_arguments(msg);
2033 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
2034 dbus_message_iter_get_basic(&value2, &freq);
2036 connman_multi_scan_ap_s *ap =
2037 (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
2039 g_strlcpy(ap->str, freq, strlen(freq) + 1);
2041 specific_scan_list = g_slist_append(specific_scan_list, ap);
2043 DBG("Failed to allocate memory");
2045 dbus_message_iter_next(&dict);
2048 err = __connman_device_request_specific_scan(technology->type, ifname, scan_type, specific_scan_list);
2050 return __connman_error_failed(msg, -err);
2052 guint list_size = g_slist_length(specific_scan_list);
2054 if (scan_type == CONNMAN_MULTI_SCAN_SSID ||
2055 scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ)
2056 g_slist_free_full(specific_scan_list, g_free);
2058 struct connman_scan_pending *pending_data =
2059 g_try_malloc0(sizeof(struct connman_scan_pending));
2061 return __connman_error_failed(msg, ENOMEM);
2064 pending_data->ifname = g_strdup(ifname);
2065 if (pending_data->ifname == NULL) {
2066 g_free(pending_data);
2067 return __connman_error_failed(msg, ENOMEM);
2072 pending_data->scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP;
2074 pending_data->scan_type = CONNMAN_SCAN_TYPE_MULTI_AP;
2075 DBG("list_size %u scan_type %d", list_size, pending_data->scan_type);
2077 pending_data->msg = dbus_message_ref(msg);
2079 technology->scan_pending =
2080 g_slist_prepend(technology->scan_pending, pending_data);
2085 static DBusMessage *get_5ghz_supported(DBusConnection *conn, DBusMessage *msg, void *data)
2088 DBusMessageIter iter, dict;
2090 struct connman_technology *technology = data;
2091 dbus_bool_t supported = false;
2092 const char *ifname = NULL;
2094 DBG("technology %p", technology);
2096 reply = dbus_message_new_method_return(msg);
2100 dbus_message_iter_init_append(reply, &iter);
2101 connman_dbus_dict_open(&iter, &dict);
2103 for (list = technology->device_list; list; list = list->next) {
2104 struct connman_device *device = list->data;
2106 supported = connman_device_get_wifi_5ghz_supported(device);
2107 ifname = connman_device_get_string(device, "Interface");
2109 DBG("ifname %s supported : %d", ifname, supported);
2110 connman_dbus_dict_append_basic(&dict, ifname,
2115 connman_dbus_dict_close(&iter, &dict);
2120 static DBusMessage *get_6ghz_supported(DBusConnection *conn, DBusMessage *msg, void *data)
2123 DBusMessageIter iter, dict;
2125 struct connman_technology *technology = data;
2126 dbus_bool_t supported = false;
2127 const char *ifname = NULL;
2129 DBG("technology %p", technology);
2131 reply = dbus_message_new_method_return(msg);
2135 dbus_message_iter_init_append(reply, &iter);
2136 connman_dbus_dict_open(&iter, &dict);
2138 for (list = technology->device_list; list; list = list->next) {
2139 struct connman_device *device = list->data;
2141 supported = connman_device_get_wifi_6ghz_supported(device);
2142 ifname = connman_device_get_string(device, "Interface");
2144 DBG("ifname %s supported : %d", ifname, supported);
2145 connman_dbus_dict_append_basic(&dict, ifname,
2150 connman_dbus_dict_close(&iter, &dict);
2155 static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data)
2158 DBusMessageIter iter, dict;
2160 struct connman_technology *technology = data;
2161 dbus_bool_t scanning = false;
2162 const char *ifname = NULL;
2164 DBG("technology %p", technology);
2166 reply = dbus_message_new_method_return(msg);
2170 dbus_message_iter_init_append(reply, &iter);
2171 connman_dbus_dict_open(&iter, &dict);
2173 for (list = technology->device_list; list; list = list->next) {
2174 struct connman_device *device = list->data;
2176 scanning = connman_device_get_scanning(device, technology->type);
2177 ifname = connman_device_get_string(device, "Interface");
2179 DBG("ifname %s scanning : %d", ifname, scanning);
2180 connman_dbus_dict_append_basic(&dict, ifname,
2185 connman_dbus_dict_close(&iter, &dict);
2190 static DBusMessage *get_max_scan_ssid(DBusConnection *conn, DBusMessage *msg, void *data)
2193 DBusMessageIter iter, dict;
2195 struct connman_technology *technology = data;
2196 dbus_int32_t max_scan_ssids = 0;
2197 const char *ifname = NULL;
2199 DBG("technology %p", technology);
2201 reply = dbus_message_new_method_return(msg);
2205 dbus_message_iter_init_append(reply, &iter);
2206 connman_dbus_dict_open(&iter, &dict);
2208 for (list = technology->device_list; list; list = list->next) {
2209 struct connman_device *device = list->data;
2211 max_scan_ssids = connman_device_get_max_scan_ssids(device);
2212 ifname = connman_device_get_string(device, "Interface");
2214 DBG("ifname %s max_scan_ssids : %d", ifname, max_scan_ssids);
2215 connman_dbus_dict_append_basic(&dict, ifname,
2220 connman_dbus_dict_close(&iter, &dict);
2225 static int technology_enable_device(struct connman_technology *technology,
2226 bool enable_device, const char *ifname, struct connman_device **device_out)
2231 for (list = technology->device_list; list; list = list->next) {
2232 struct connman_device *device = list->data;
2233 const char *str = connman_device_get_string(device, "Interface");
2235 if (g_strcmp0(str, ifname) != 0)
2239 err = __connman_device_enable(device);
2241 err = __connman_device_disable(device);
2243 *device_out = device;
2250 static DBusMessage *technology_set_device_powered(struct connman_technology *technology,
2251 DBusMessage *msg, bool powered, const char *ifname)
2253 DBusMessage *reply = NULL;
2254 struct connman_device *device = NULL;
2257 err = technology_enable_device(technology, powered, ifname, &device);
2259 if (err == -EINPROGRESS) {
2261 connman_device_set_pending_reply(device, msg);
2263 } else if (err == -EALREADY) {
2265 reply = __connman_error_already_enabled(msg);
2267 reply = __connman_error_already_disabled(msg);
2269 reply = __connman_error_failed(msg, -err);
2271 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2276 static DBusMessage *set_device_power(DBusConnection *conn,
2277 DBusMessage *msg, void *data)
2279 struct connman_technology *technology = data;
2280 DBusMessageIter iter;
2285 DBG("conn %p", conn);
2287 if (!dbus_message_iter_init(msg, &iter))
2288 return __connman_error_invalid_arguments(msg);
2290 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2291 return __connman_error_invalid_arguments(msg);
2293 dbus_message_iter_get_basic(&iter, &name);
2294 dbus_message_iter_next(&iter);
2296 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
2297 return __connman_error_invalid_arguments(msg);
2299 DBG("interface name %s", name);
2303 if (len + 1 > IFNAMSIZ)
2304 return __connman_error_invalid_arguments(msg);
2306 dbus_message_iter_get_basic(&iter, &enable);
2307 DBG("powered %s", enable ? "TRUE" : "FALSE");
2309 return technology_set_device_powered(technology, msg, enable, name);
2312 static DBusMessage *set_bssid(DBusConnection *conn,
2313 DBusMessage *msg, void *data)
2315 DBusMessageIter iter;
2319 DBG("conn %p", conn);
2321 if (!dbus_message_iter_init(msg, &iter))
2322 return __connman_error_invalid_arguments(msg);
2324 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2325 return __connman_error_invalid_arguments(msg);
2327 dbus_message_iter_get_basic(&iter, &name);
2328 dbus_message_iter_next(&iter);
2330 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2331 return __connman_error_invalid_arguments(msg);
2333 dbus_message_iter_get_basic(&iter, &bssid);
2335 DBG("interface name %s bssid %s", name, bssid);
2339 if (len + 1 > IFNAMSIZ)
2340 return __connman_error_invalid_arguments(msg);
2342 set_connman_bssid(SET_BSSID, bssid, name);
2344 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2346 static struct connman_technology *technology_get(enum connman_service_type type);
2348 void technology_save_device(struct connman_device *device)
2350 struct connman_technology *technology;
2351 enum connman_service_type type;
2353 type = __connman_device_get_service_type(device);
2355 if (type != CONNMAN_SERVICE_TYPE_WIFI)
2358 technology = technology_get(type);
2362 if (!g_slist_find(technology->device_list, device))
2367 const char *name = get_name(technology->type);
2369 DBG("technology %p type %d name %s", technology, technology->type,
2374 keyfile = __connman_storage_load_global();
2376 keyfile = g_key_file_new();
2378 identifier = g_strdup_printf("%s", name);
2382 GSList *list = NULL;
2383 gchar **ifname_list = NULL;
2384 guint dev_count = g_slist_length(technology->device_list);
2386 if (dev_count >= 1) {
2387 GString *ifname_str = g_string_new(NULL);
2390 for (list = technology->device_list; list; list = list->next) {
2391 struct connman_device *device = list->data;
2393 if (connman_device_get_powered(device)) {
2394 const char *ifname = connman_device_get_string(device, "Interface");
2396 if (ifname_str->len > 0)
2397 g_string_append_printf(ifname_str, " %s", ifname);
2399 g_string_append(ifname_str, ifname);
2403 if (ifname_str->len > 0) {
2404 ifname_list = g_strsplit_set(ifname_str->str, " ", 0);
2405 dev_count = g_strv_length(ifname_list);
2406 g_key_file_set_string_list(keyfile, identifier, "Enable.Devices",
2407 (const gchar **) ifname_list, dev_count);
2409 technology->enable_persistent = true;
2411 g_key_file_remove_key(keyfile, identifier, "Enable.Devices", NULL);
2412 technology->enable_persistent = false;
2415 g_strfreev(ifname_list);
2416 g_string_free(ifname_str, TRUE);
2420 g_key_file_set_boolean(keyfile, identifier, "Enable",
2421 technology->enable_persistent);
2423 g_key_file_set_boolean(keyfile, identifier, "Tethering",
2424 technology->tethering_persistent);
2426 if (technology->tethering_ident)
2427 g_key_file_set_string(keyfile, identifier,
2428 "Tethering.Identifier",
2429 technology->tethering_ident);
2431 if (technology->tethering_passphrase)
2432 g_key_file_set_string(keyfile, identifier,
2433 "Tethering.Passphrase",
2434 technology->tethering_passphrase);
2439 __connman_storage_save_global(keyfile);
2441 g_key_file_free(keyfile);
2445 #if defined TIZEN_EXT_WIFI_MESH
2446 bool __connman_technology_get_connected(enum connman_service_type type)
2448 struct connman_technology *technology;
2450 technology = technology_find(type);
2455 return technology->connected;
2458 void __connman_technology_mesh_interface_create_finished(
2459 enum connman_service_type type, bool success,
2463 struct connman_technology *technology;
2465 technology = technology_find(type);
2467 DBG("technology %p success %d", technology, success);
2472 msg = technology->mesh_dbus_msg;
2474 DBG("No pending dbus message");
2479 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2480 __connman_device_request_scan(technology->type);
2482 reply = g_dbus_create_error(msg, CONNMAN_ERROR_INTERFACE
2483 ".MeshInterfaceAddFailed", "%s", error);
2484 g_dbus_send_message(connection, reply);
2485 dbus_message_unref(msg);
2486 technology->mesh_dbus_msg = NULL;
2489 void __connman_technology_mesh_interface_remove_finished(
2490 enum connman_service_type type, bool success)
2493 struct connman_technology *technology;
2495 technology = technology_find(type);
2497 DBG("technology %p success %d", technology, success);
2499 if (!technology || !technology->mesh_dbus_msg)
2502 msg = technology->mesh_dbus_msg;
2504 DBG("No pending dbus message");
2509 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2511 reply = __connman_error_failed(msg, EINVAL);
2512 g_dbus_send_message(connection, reply);
2513 dbus_message_unref(msg);
2514 technology->mesh_dbus_msg = NULL;
2517 void __connman_technology_notify_abort_scan(enum connman_service_type type,
2521 struct connman_technology *technology;
2523 technology = technology_find(type);
2525 DBG("technology %p result %d", technology, result);
2527 if (!technology || !technology->mesh_dbus_msg)
2530 msg = technology->mesh_dbus_msg;
2532 DBG("No pending dbus message");
2537 reply = __connman_error_scan_abort_failed(msg);
2539 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2541 g_dbus_send_message(connection, reply);
2542 dbus_message_unref(msg);
2543 technology->mesh_dbus_msg = NULL;
2546 static DBusMessage *mesh_commands(DBusConnection *conn,
2547 DBusMessage *msg, void *data)
2549 struct connman_technology *technology = data;
2550 DBusMessageIter iter, value, dict;
2551 const char *cmd = NULL, *ifname = NULL, *parent_ifname = NULL;
2554 DBG("conn %p", conn);
2556 if (technology->type != CONNMAN_SERVICE_TYPE_MESH)
2557 return __connman_error_invalid_arguments(msg);
2559 if (!dbus_message_iter_init(msg, &iter))
2560 return __connman_error_invalid_arguments(msg);
2562 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2563 return __connman_error_invalid_arguments(msg);
2565 dbus_message_iter_get_basic(&iter, &cmd);
2566 dbus_message_iter_next(&iter);
2568 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
2569 return __connman_error_invalid_arguments(msg);
2571 dbus_message_iter_recurse(&iter, &value);
2573 if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_ARRAY)
2574 return __connman_error_invalid_arguments(msg);
2576 DBG("Mesh Command %s", cmd);
2577 if (g_str_equal(cmd, "MeshInterfaceAdd")) {
2578 dbus_message_iter_recurse(&value, &dict);
2579 const char *bridge_ifname = NULL;
2580 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2581 DBusMessageIter entry, value2;
2585 dbus_message_iter_recurse(&dict, &entry);
2587 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2588 return __connman_error_invalid_arguments(msg);
2590 dbus_message_iter_get_basic(&entry, &key);
2591 dbus_message_iter_next(&entry);
2593 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2594 return __connman_error_invalid_arguments(msg);
2596 dbus_message_iter_recurse(&entry, &value2);
2598 type = dbus_message_iter_get_arg_type(&value2);
2600 if (g_str_equal(key, "Ifname")) {
2601 if (type != DBUS_TYPE_STRING)
2602 return __connman_error_invalid_arguments(msg);
2604 dbus_message_iter_get_basic(&value2, &ifname);
2605 } else if (g_str_equal(key, "ParentIfname")) {
2606 if (type != DBUS_TYPE_STRING)
2607 return __connman_error_invalid_arguments(msg);
2609 dbus_message_iter_get_basic(&value2, &parent_ifname);
2610 } else if (g_str_equal(key, "BridgeIfname")) {
2611 if (type != DBUS_TYPE_STRING)
2612 return __connman_error_invalid_arguments(msg);
2614 dbus_message_iter_get_basic(&value2, &bridge_ifname);
2616 dbus_message_iter_next(&dict);
2618 DBG("Mesh Ifname %s parent %s bridge %s", ifname, parent_ifname,
2619 bridge_ifname ? bridge_ifname : "NULL");
2620 err = __connman_mesh_add_virtual_interface(ifname, parent_ifname,
2624 DBG("Failed to add virtual mesh interface");
2625 return __connman_error_failed(msg, -err);
2628 DBG("Successfully added virtual mesh interface");
2630 dbus_message_ref(msg);
2631 technology->mesh_dbus_msg = msg;
2633 } else if (g_str_equal(cmd, "MeshInterfaceRemove")) {
2634 dbus_message_iter_recurse(&value, &dict);
2635 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2636 DBusMessageIter entry, value2;
2640 dbus_message_iter_recurse(&dict, &entry);
2642 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2643 return __connman_error_invalid_arguments(msg);
2645 dbus_message_iter_get_basic(&entry, &key);
2646 dbus_message_iter_next(&entry);
2648 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2649 return __connman_error_invalid_arguments(msg);
2651 dbus_message_iter_recurse(&entry, &value2);
2653 type = dbus_message_iter_get_arg_type(&value2);
2655 if (g_str_equal(key, "Ifname")) {
2656 if (type != DBUS_TYPE_STRING)
2657 return __connman_error_invalid_arguments(msg);
2659 dbus_message_iter_get_basic(&value2, &ifname);
2661 dbus_message_iter_next(&dict);
2663 DBG("Mesh Ifname %s", ifname);
2664 err = __connman_mesh_remove_virtual_interface(ifname);
2667 DBG("Failed to remove virtual mesh interface");
2668 return __connman_error_failed(msg, -err);
2671 DBG("Successfully removed virtual mesh interface");
2673 dbus_message_ref(msg);
2674 technology->mesh_dbus_msg = msg;
2676 } else if (g_str_equal(cmd, "MeshCreateNetwork")) {
2677 struct connman_mesh *connman_mesh;
2678 const char *name = NULL;
2679 const char *sec_type = NULL;
2680 const char *mesh_ifname = NULL;
2681 char *identifier, *group, *address;
2682 unsigned int freq = 0;
2683 unsigned int ieee80211w = 0;
2686 dbus_message_iter_recurse(&value, &dict);
2687 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2688 DBusMessageIter entry, value2;
2692 dbus_message_iter_recurse(&dict, &entry);
2694 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2695 return __connman_error_invalid_arguments(msg);
2697 dbus_message_iter_get_basic(&entry, &key);
2698 dbus_message_iter_next(&entry);
2700 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2701 return __connman_error_invalid_arguments(msg);
2703 dbus_message_iter_recurse(&entry, &value2);
2705 type = dbus_message_iter_get_arg_type(&value2);
2707 if (g_str_equal(key, "Name")) {
2708 if (type != DBUS_TYPE_STRING)
2709 return __connman_error_invalid_arguments(msg);
2711 dbus_message_iter_get_basic(&value2, &name);
2712 } else if (g_str_equal(key, "Frequency")) {
2713 if (type != DBUS_TYPE_UINT16)
2714 return __connman_error_invalid_arguments(msg);
2716 dbus_message_iter_get_basic(&value2, &freq);
2717 } else if (g_str_equal(key, "Security")) {
2718 if (type != DBUS_TYPE_STRING)
2719 return __connman_error_invalid_arguments(msg);
2721 dbus_message_iter_get_basic(&value2, &sec_type);
2722 } else if (g_str_equal(key, "Pmf")) {
2723 if (type != DBUS_TYPE_UINT16)
2724 return __connman_error_invalid_arguments(msg);
2726 dbus_message_iter_get_basic(&value2, &ieee80211w);
2728 dbus_message_iter_next(&dict);
2731 if (name == NULL || sec_type == NULL || freq == 0)
2732 return __connman_error_invalid_arguments(msg);
2734 DBG("Name %s Frequency %d Security type %s Pmf %u",
2735 name, freq, sec_type, ieee80211w);
2737 if (g_strcmp0(sec_type, "none") != 0 &&
2738 g_strcmp0(sec_type, "sae") != 0) {
2739 DBG("Unsupported security");
2740 return __connman_error_invalid_arguments(msg);
2743 mesh_ifname = connman_mesh_get_interface_name();
2745 if (!connman_mesh_is_interface_created()) {
2746 DBG("Mesh interface doesn't exists");
2747 return __connman_error_invalid_command(msg);
2750 str = g_string_sized_new((strlen(name) * 2) + 24);
2752 for (i = 0; name[i]; i++)
2753 g_string_append_printf(str, "%02x", name[i]);
2755 g_string_append_printf(str, "_mesh");
2757 if (g_strcmp0(sec_type, "none") == 0)
2758 g_string_append_printf(str, "_none");
2759 else if (g_strcmp0(sec_type, "sae") == 0)
2760 g_string_append_printf(str, "_sae");
2762 group = g_string_free(str, FALSE);
2764 identifier = connman_inet_ifaddr(mesh_ifname);
2765 address = connman_inet_ifname2addr(mesh_ifname);
2767 connman_mesh = connman_mesh_create(identifier, group);
2768 connman_mesh_set_name(connman_mesh, name);
2769 connman_mesh_set_address(connman_mesh, address);
2770 connman_mesh_set_security(connman_mesh, sec_type);
2771 connman_mesh_set_frequency(connman_mesh, freq);
2772 connman_mesh_set_index(connman_mesh, connman_inet_ifindex(mesh_ifname));
2773 connman_mesh_set_peer_type(connman_mesh,
2774 CONNMAN_MESH_PEER_TYPE_CREATED);
2775 connman_mesh_set_ieee80211w(connman_mesh, ieee80211w);
2777 connman_mesh_register(connman_mesh);
2781 DBG("Successfully Created Mesh Network");
2782 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2784 } else if (g_str_equal(cmd, "AbortScan")) {
2785 DBG("Abort Scan method");
2786 err = __connman_device_abort_scan(technology->type);
2788 DBG("Failed to abort scan");
2789 return __connman_error_failed(msg, -err);
2792 DBG("Successfully requested to abort scan");
2793 dbus_message_ref(msg);
2794 technology->mesh_dbus_msg = msg;
2796 } else if (g_str_equal(cmd, "MeshSpecificScan")) {
2797 const char *name = NULL;
2798 unsigned int freq = 0;
2799 dbus_message_iter_recurse(&value, &dict);
2800 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2801 DBusMessageIter entry, value2;
2805 dbus_message_iter_recurse(&dict, &entry);
2807 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2808 return __connman_error_invalid_arguments(msg);
2810 dbus_message_iter_get_basic(&entry, &key);
2811 dbus_message_iter_next(&entry);
2813 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2814 return __connman_error_invalid_arguments(msg);
2816 dbus_message_iter_recurse(&entry, &value2);
2818 type = dbus_message_iter_get_arg_type(&value2);
2820 if (g_str_equal(key, "Name")) {
2821 if (type != DBUS_TYPE_STRING)
2822 return __connman_error_invalid_arguments(msg);
2824 dbus_message_iter_get_basic(&value2, &name);
2825 } else if (g_str_equal(key, "Frequency")) {
2826 if (type != DBUS_TYPE_UINT16)
2827 return __connman_error_invalid_arguments(msg);
2829 dbus_message_iter_get_basic(&value2, &freq);
2831 dbus_message_iter_next(&dict);
2834 DBG("MeshID %s Frequency %d sender %s", name, freq,
2835 dbus_message_get_sender(msg));
2837 struct connman_scan_pending *pending_data =
2838 g_try_malloc0(sizeof(struct connman_scan_pending));
2840 return __connman_error_failed(msg, ENOMEM);
2842 pending_data->msg = dbus_message_ref(msg);
2844 technology->scan_pending =
2845 g_slist_prepend(technology->scan_pending, pending_data);
2847 err = __connman_device_request_mesh_specific_scan(technology->type,
2850 reply_scan_pending(technology, err);
2852 DBG("Successfully requested to scan specific Mesh Network");
2854 } else if (g_str_equal(cmd, "SetMeshGate")) {
2855 unsigned int hwmp_rootmode = 0;
2856 bool gate_announce = false;
2857 unsigned int stp = 0;
2859 dbus_message_iter_recurse(&value, &dict);
2860 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2861 DBusMessageIter entry, value2;
2865 dbus_message_iter_recurse(&dict, &entry);
2867 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2868 return __connman_error_invalid_arguments(msg);
2870 dbus_message_iter_get_basic(&entry, &key);
2871 dbus_message_iter_next(&entry);
2873 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2874 return __connman_error_invalid_arguments(msg);
2876 dbus_message_iter_recurse(&entry, &value2);
2878 type = dbus_message_iter_get_arg_type(&value2);
2880 if (g_str_equal(key, "GateAnnounce")) {
2881 if (type != DBUS_TYPE_BOOLEAN)
2882 return __connman_error_invalid_arguments(msg);
2884 dbus_message_iter_get_basic(&value2, &gate_announce);
2885 } else if (g_str_equal(key, "HWMPRootMode")) {
2886 if (type != DBUS_TYPE_UINT16)
2887 return __connman_error_invalid_arguments(msg);
2889 dbus_message_iter_get_basic(&value2, &hwmp_rootmode);
2890 } else if (g_str_equal(key, "STP")) {
2891 if (type != DBUS_TYPE_UINT16)
2892 return __connman_error_invalid_arguments(msg);
2894 dbus_message_iter_get_basic(&value2, &stp);
2896 dbus_message_iter_next(&dict);
2899 DBG("GateAnnounce %d HWMPRootMode %d STP %d sender %s",
2900 gate_announce, hwmp_rootmode, stp, dbus_message_get_sender(msg));
2902 err = __connman_mesh_set_stp_gate_announce(gate_announce,
2907 return __connman_error_failed(msg, -err);
2909 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2911 return __connman_error_invalid_command(msg);
2916 static const GDBusMethodTable technology_methods[] = {
2917 { GDBUS_DEPRECATED_METHOD("GetProperties",
2918 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
2920 { GDBUS_ASYNC_METHOD("SetProperty",
2921 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
2922 NULL, set_property) },
2923 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
2924 #if defined TIZEN_EXT
2925 { GDBUS_ASYNC_METHOD("ScanDevice", GDBUS_ARGS({ "interface_name", "s" }),
2926 NULL, scan_device) },
2927 { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }),
2928 NULL, specific_scan) },
2929 { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }),
2931 { GDBUS_METHOD("Get5GhzSupported", NULL, GDBUS_ARGS({ "supported", "a{sv}" }),
2932 get_5ghz_supported) },
2933 { GDBUS_METHOD("Get6GHzSupported", NULL, GDBUS_ARGS({ "supported", "a{sv}" }),
2934 get_6ghz_supported) },
2935 { GDBUS_METHOD("GetMaxScanSsid", NULL, GDBUS_ARGS({ "maxscanssid", "a{sv}" }),
2936 get_max_scan_ssid) },
2937 { GDBUS_ASYNC_METHOD("SetDevicePower",
2938 GDBUS_ARGS({ "ifname", "s" }, { "value", "b" }),
2939 NULL, set_device_power) },
2940 { GDBUS_ASYNC_METHOD("SetBSSID",
2941 GDBUS_ARGS({ "ifname", "s" }, { "bssid", "s" }),
2944 #if defined TIZEN_EXT_WIFI_MESH
2945 { GDBUS_ASYNC_METHOD("MeshCommands",
2946 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
2947 NULL, mesh_commands) },
2952 static const GDBusSignalTable technology_signals[] = {
2953 { GDBUS_SIGNAL("PropertyChanged",
2954 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
2955 #if defined TIZEN_EXT
2956 { GDBUS_SIGNAL("DeviceChanged",
2957 GDBUS_ARGS({ "device_property", "a{sv}" })) },
2958 { GDBUS_SIGNAL("DeviceDetected",
2959 GDBUS_ARGS({ "ifname", "s" }, { "detected", "b" })) },
2964 static bool technology_dbus_register(struct connman_technology *technology)
2966 if (technology->dbus_registered ||
2967 (technology->rfkill_driven &&
2968 technology->hardblocked))
2971 if (!g_dbus_register_interface(connection, technology->path,
2972 CONNMAN_TECHNOLOGY_INTERFACE,
2973 technology_methods, technology_signals,
2974 NULL, technology, NULL)) {
2975 connman_error("Failed to register %s", technology->path);
2979 technology_added_signal(technology);
2980 technology->dbus_registered = true;
2985 static void technology_dbus_unregister(struct connman_technology *technology)
2987 if (!technology->dbus_registered)
2990 technology_removed_signal(technology);
2991 g_dbus_unregister_interface(connection, technology->path,
2992 CONNMAN_TECHNOLOGY_INTERFACE);
2994 technology->dbus_registered = false;
2997 static void technology_put(struct connman_technology *technology)
2999 DBG("technology %p", technology);
3001 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
3004 reply_scan_pending(technology, -EINTR);
3006 while (technology->driver_list) {
3007 struct connman_technology_driver *driver;
3009 driver = technology->driver_list->data;
3012 driver->remove(technology);
3014 technology->driver_list =
3015 g_slist_delete_link(technology->driver_list,
3016 technology->driver_list);
3019 __connman_technology_notify_device_detected(technology, "", false);
3021 technology_list = g_slist_remove(technology_list, technology);
3023 technology_dbus_unregister(technology);
3025 g_slist_free(technology->device_list);
3027 if (technology->pending_reply) {
3028 dbus_message_unref(technology->pending_reply);
3029 technology->pending_reply = NULL;
3030 g_source_remove(technology->pending_timeout);
3031 technology->pending_timeout = 0;
3034 g_strfreev(technology->enabled_devices);
3036 g_free(technology->path);
3037 g_free(technology->regdom);
3038 g_free(technology->tethering_ident);
3039 g_free(technology->tethering_passphrase);
3043 static struct connman_technology *technology_get(enum connman_service_type type)
3045 GSList *tech_drivers = NULL;
3046 struct connman_technology_driver *driver;
3047 struct connman_technology *technology;
3051 DBG("type %d", type);
3053 str = __connman_service_type2string(type);
3057 technology = technology_find(type);
3059 #if defined TIZEN_EXT_WIFI_MESH
3060 if (type != CONNMAN_SERVICE_TYPE_P2P &&
3061 type != CONNMAN_SERVICE_TYPE_MESH)
3063 if (type != CONNMAN_SERVICE_TYPE_P2P)
3065 __sync_fetch_and_add(&technology->refcount, 1);
3069 /* First check if we have a driver for this technology type */
3070 for (list = driver_list; list; list = list->next) {
3071 driver = list->data;
3073 if (driver->type == type) {
3074 DBG("technology %p driver %p", technology, driver);
3075 tech_drivers = g_slist_append(tech_drivers, driver);
3079 if (!tech_drivers) {
3080 DBG("No matching drivers found for %s.",
3081 __connman_service_type2string(type));
3085 technology = g_try_new0(struct connman_technology, 1);
3089 technology->refcount = 1;
3090 technology->type = type;
3091 technology->path = g_strdup_printf("%s/technology/%s",
3094 #if defined TIZEN_EXT_WIFI_MESH
3095 if (type == CONNMAN_SERVICE_TYPE_MESH) {
3096 struct connman_technology *wifi;
3098 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
3100 technology->enabled = wifi->enabled;
3104 technology_load(technology);
3105 technology_list = g_slist_prepend(technology_list, technology);
3106 technology->driver_list = tech_drivers;
3108 for (list = tech_drivers; list; list = list->next) {
3109 driver = list->data;
3111 if (driver->probe && driver->probe(technology) < 0)
3112 DBG("Driver probe failed for technology %p",
3116 if (!technology_dbus_register(technology)) {
3117 technology_put(technology);
3121 if (type == CONNMAN_SERVICE_TYPE_P2P) {
3122 struct connman_technology *wifi;
3125 enable = technology->enable_persistent;
3127 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
3129 enable = wifi->enabled;
3131 technology_affect_devices(technology, enable);
3134 DBG("technology %p %s", technology, get_name(technology->type));
3139 int connman_technology_driver_register(struct connman_technology_driver *driver)
3142 struct connman_device *device;
3143 enum connman_service_type type;
3145 for (list = driver_list; list; list = list->next) {
3146 if (list->data == driver)
3150 DBG("Registering %s driver", driver->name);
3152 driver_list = g_slist_insert_sorted(driver_list, driver,
3156 * Check for technology less devices if this driver
3157 * can service any of them.
3159 for (list = techless_device_list; list; list = list->next) {
3160 device = list->data;
3162 type = __connman_device_get_service_type(device);
3163 if (type != driver->type)
3166 techless_device_list = g_slist_remove(techless_device_list,
3169 __connman_technology_add_device(device);
3172 /* Check for orphaned rfkill switches. */
3173 g_hash_table_foreach(rfkill_list, rfkill_check,
3174 GINT_TO_POINTER(driver->type));
3177 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
3178 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
3182 #if defined TIZEN_EXT_WIFI_MESH
3183 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
3184 if (!technology_get(CONNMAN_SERVICE_TYPE_MESH))
3192 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
3194 GSList *list, *tech_drivers;
3195 struct connman_technology *technology;
3196 struct connman_technology_driver *current;
3198 DBG("Unregistering driver %p name %s", driver, driver->name);
3200 for (list = technology_list; list; list = list->next) {
3201 technology = list->data;
3203 for (tech_drivers = technology->driver_list; tech_drivers;
3204 tech_drivers = g_slist_next(tech_drivers)) {
3205 current = tech_drivers->data;
3206 if (driver != current)
3210 driver->remove(technology);
3212 technology->driver_list =
3213 g_slist_remove(technology->driver_list,
3219 driver_list = g_slist_remove(driver_list, driver);
3221 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
3222 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
3224 technology_put(technology);
3226 #if defined TIZEN_EXT_WIFI_MESH
3227 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
3228 technology = technology_find(CONNMAN_SERVICE_TYPE_MESH);
3230 technology_put(technology);
3235 void __connman_technology_add_interface(enum connman_service_type type,
3236 int index, const char *ident)
3238 struct connman_technology *technology;
3239 GSList *tech_drivers;
3240 struct connman_technology_driver *driver;
3244 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3245 case CONNMAN_SERVICE_TYPE_SYSTEM:
3247 case CONNMAN_SERVICE_TYPE_ETHERNET:
3248 case CONNMAN_SERVICE_TYPE_WIFI:
3249 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3250 case CONNMAN_SERVICE_TYPE_CELLULAR:
3251 case CONNMAN_SERVICE_TYPE_GPS:
3252 case CONNMAN_SERVICE_TYPE_VPN:
3253 case CONNMAN_SERVICE_TYPE_GADGET:
3254 case CONNMAN_SERVICE_TYPE_P2P:
3255 #if defined TIZEN_EXT_WIFI_MESH
3256 case CONNMAN_SERVICE_TYPE_MESH:
3261 name = connman_inet_ifname(index);
3262 connman_info("Adding interface %s [ %s ]", name,
3263 __connman_service_type2string(type));
3265 technology = technology_find(type);
3270 for (tech_drivers = technology->driver_list; tech_drivers;
3271 tech_drivers = g_slist_next(tech_drivers)) {
3272 driver = tech_drivers->data;
3274 if (driver->add_interface)
3275 driver->add_interface(technology, index, name, ident);
3279 * At this point we can try to enable tethering automatically as
3280 * now the interfaces are set properly.
3282 if (technology->tethering_persistent)
3283 enable_tethering(technology);
3289 void __connman_technology_remove_interface(enum connman_service_type type,
3290 int index, const char *ident)
3292 struct connman_technology *technology;
3293 GSList *tech_drivers;
3294 struct connman_technology_driver *driver;
3298 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3299 case CONNMAN_SERVICE_TYPE_SYSTEM:
3301 case CONNMAN_SERVICE_TYPE_ETHERNET:
3302 case CONNMAN_SERVICE_TYPE_WIFI:
3303 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3304 case CONNMAN_SERVICE_TYPE_CELLULAR:
3305 case CONNMAN_SERVICE_TYPE_GPS:
3306 case CONNMAN_SERVICE_TYPE_VPN:
3307 case CONNMAN_SERVICE_TYPE_GADGET:
3308 case CONNMAN_SERVICE_TYPE_P2P:
3309 #if defined TIZEN_EXT_WIFI_MESH
3310 case CONNMAN_SERVICE_TYPE_MESH:
3315 name = connman_inet_ifname(index);
3316 connman_info("Remove interface %s [ %s ]", name,
3317 __connman_service_type2string(type));
3320 technology = technology_find(type);
3325 for (tech_drivers = technology->driver_list; tech_drivers;
3326 tech_drivers = g_slist_next(tech_drivers)) {
3327 driver = tech_drivers->data;
3329 if (driver->remove_interface)
3330 driver->remove_interface(technology, index);
3334 int __connman_technology_add_device(struct connman_device *device)
3336 struct connman_technology *technology;
3337 enum connman_service_type type;
3339 type = __connman_device_get_service_type(device);
3341 DBG("device %p type %s", device, get_name(type));
3343 technology = technology_get(type);
3346 * Since no driver can be found for this device at the moment we
3347 * add it to the techless device list.
3349 techless_device_list = g_slist_prepend(techless_device_list,
3355 __sync_synchronize();
3356 if (technology->rfkill_driven) {
3357 if (technology->enabled)
3358 __connman_device_enable(device);
3360 __connman_device_disable(device);
3365 if (technology->enable_persistent &&
3366 !global_offlinemode) {
3367 #if defined TIZEN_EXT
3370 if (technology->enabled_devices && type == CONNMAN_SERVICE_TYPE_WIFI) {
3373 const char *ifname = connman_device_get_string(device, "Interface");
3375 while (technology->enabled_devices[i]) {
3376 if (g_strcmp0(technology->enabled_devices[i], ifname) == 0) {
3385 err = __connman_device_enable(device);
3387 int err = __connman_device_enable(device);
3390 * connman_technology_add_device() calls __connman_device_enable()
3391 * but since the device is already enabled, the call does not
3392 * propagate through to connman_technology_enabled via
3393 * connman_device_set_powered.
3395 if (err == -EALREADY)
3396 __connman_technology_enabled(type);
3398 /* if technology persistent state is offline */
3399 if (!technology->enable_persistent)
3400 __connman_device_disable(device);
3403 technology->device_list = g_slist_prepend(technology->device_list,
3406 #if defined TIZEN_EXT
3407 technology_save_device(device);
3409 const char *ifname = connman_device_get_string(device, "Interface");
3410 __connman_technology_notify_device_detected(technology, ifname, true);
3412 connman_device_set_mac_policy(device, technology->mac_policy);
3413 connman_device_set_preassoc_mac_policy(device, technology->preassoc_mac_policy);
3414 connman_device_set_random_mac_lifetime(device, technology->random_mac_lifetime);
3419 int __connman_technology_remove_device(struct connman_device *device)
3421 struct connman_technology *technology;
3422 enum connman_service_type type;
3424 DBG("device %p", device);
3426 type = __connman_device_get_service_type(device);
3428 technology = technology_find(type);
3430 techless_device_list = g_slist_remove(techless_device_list,
3435 technology->device_list = g_slist_remove(technology->device_list,
3438 #if defined TIZEN_EXT
3439 technology_save_device(device);
3442 if (technology->tethering)
3443 set_tethering(technology, false);
3445 technology_put(technology);
3450 int __connman_technology_enabled(enum connman_service_type type)
3452 struct connman_technology *technology;
3454 technology = technology_find(type);
3458 DBG("technology %p type %s rfkill %d enabled %d", technology,
3459 get_name(type), technology->rfkill_driven,
3460 technology->enabled);
3462 #if !defined TIZEN_EXT
3463 if (technology->rfkill_driven) {
3464 if (technology->tethering_persistent)
3465 enable_tethering(technology);
3470 return technology_enabled(technology);
3473 int __connman_technology_disabled(enum connman_service_type type)
3475 struct connman_technology *technology;
3478 technology = technology_find(type);
3482 #if !defined TIZEN_EXT
3483 if (technology->rfkill_driven)
3487 for (list = technology->device_list; list; list = list->next) {
3488 struct connman_device *device = list->data;
3490 if (connman_device_get_powered(device))
3494 return technology_disabled(technology);
3497 int __connman_technology_set_offlinemode(bool offlinemode)
3500 int err = -EINVAL, enabled_tech_count = 0;
3502 if (global_offlinemode == offlinemode)
3505 DBG("offlinemode %s", offlinemode ? "On" : "Off");
3508 * This is a bit tricky. When you set offlinemode, there is no
3509 * way to differentiate between attempting offline mode and
3510 * resuming offlinemode from last saved profile. We need that
3511 * information in rfkill_update, otherwise it falls back on the
3512 * technology's persistent state. Hence we set the offline mode here
3513 * but save it & call the notifier only if it is successful.
3516 global_offlinemode = offlinemode;
3518 /* Traverse technology list, enable/disable each technology. */
3519 for (list = technology_list; list; list = list->next) {
3520 struct connman_technology *technology = list->data;
3523 err = technology_disable(technology);
3525 if (technology->hardblocked)
3528 if (technology->enable_persistent) {
3529 err = technology_enable(technology);
3530 enabled_tech_count++;
3535 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
3536 (err == -EINVAL && enabled_tech_count == 0)) {
3537 connman_technology_save_offlinemode();
3538 __connman_notifier_offlinemode(offlinemode);
3540 global_offlinemode = connman_technology_load_offlinemode();
3545 #if defined TIZEN_EXT_WIFI_MESH
3546 static gboolean __add_ethernet_to_bridge(gpointer data)
3549 __connman_mesh_add_ethernet_to_bridge();
3554 void __connman_technology_set_connected(enum connman_service_type type,
3557 struct connman_technology *technology;
3560 technology = technology_find(type);
3564 DBG("technology %p connected %d", technology, connected);
3566 technology->connected = connected;
3568 #if defined TIZEN_EXT_WIFI_MESH
3569 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET && connected)
3570 g_idle_add(__add_ethernet_to_bridge, NULL);
3574 connman_dbus_property_changed_basic(technology->path,
3575 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
3576 DBUS_TYPE_BOOLEAN, &val);
3579 static bool technology_apply_rfkill_change(struct connman_technology *technology,
3584 bool hardblock_changed = false;
3586 GList *start, *list;
3588 DBG("technology %p --> %d/%d vs %d/%d",
3589 technology, softblock, hardblock,
3590 technology->softblocked, technology->hardblocked);
3592 if (technology->hardblocked == hardblock)
3593 goto softblock_change;
3595 if (!(new_rfkill && !hardblock)) {
3596 start = g_hash_table_get_values(rfkill_list);
3598 for (list = start; list; list = list->next) {
3599 struct connman_rfkill *rfkill = list->data;
3601 if (rfkill->type != technology->type)
3604 if (rfkill->hardblock != hardblock)
3612 goto softblock_change;
3614 technology->hardblocked = hardblock;
3615 hardblock_changed = true;
3618 if (!apply && technology->softblocked != softblock)
3622 return technology->hardblocked;
3624 technology->softblocked = softblock;
3626 if (technology->hardblocked ||
3627 technology->softblocked) {
3628 if (technology_disabled(technology) != -EALREADY)
3629 technology_affect_devices(technology, false);
3630 } else if (!technology->hardblocked &&
3631 !technology->softblocked) {
3632 if (technology_enabled(technology) != -EALREADY)
3633 technology_affect_devices(technology, true);
3636 if (hardblock_changed) {
3637 if (technology->hardblocked) {
3638 DBG("%s is switched off.", get_name(technology->type));
3639 technology_dbus_unregister(technology);
3641 DBG("%s is switched on.", get_name(technology->type));
3642 technology_dbus_register(technology);
3644 if (global_offlinemode)
3645 __connman_rfkill_block(technology->type, true);
3649 return technology->hardblocked;
3652 int __connman_technology_add_rfkill(unsigned int index,
3653 enum connman_service_type type,
3657 struct connman_technology *technology;
3658 struct connman_rfkill *rfkill;
3660 DBG("index %u type %d soft %u hard %u", index, type,
3661 softblock, hardblock);
3663 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3667 rfkill = g_try_new0(struct connman_rfkill, 1);
3671 rfkill->index = index;
3672 rfkill->type = type;
3673 rfkill->softblock = softblock;
3674 rfkill->hardblock = hardblock;
3676 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
3679 #if defined TIZEN_EXT
3680 /* Fix Svace Issue [WGID: 1348]. */
3683 technology = technology_get(type);
3684 /* If there is no driver for this type, ignore it. */
3688 technology->rfkill_driven = true;
3690 #if !defined TIZEN_EXT
3691 /* If hardblocked, there is no need to handle softblocked state */
3692 if (technology_apply_rfkill_change(technology,
3693 softblock, hardblock, true))
3697 if (global_offlinemode)
3701 * Depending on softblocked state we unblock/block according to
3702 * offlinemode and persistente state.
3704 if (technology->softblocked &&
3705 technology->enable_persistent)
3706 return __connman_rfkill_block(type, false);
3707 else if (!technology->softblocked &&
3708 !technology->enable_persistent)
3709 return __connman_rfkill_block(type, true);
3714 int __connman_technology_update_rfkill(unsigned int index,
3715 enum connman_service_type type,
3719 struct connman_technology *technology;
3720 struct connman_rfkill *rfkill;
3722 DBG("index %u soft %u hard %u", index, softblock, hardblock);
3724 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3728 if (rfkill->softblock == softblock &&
3729 rfkill->hardblock == hardblock)
3732 rfkill->softblock = softblock;
3733 rfkill->hardblock = hardblock;
3735 technology = technology_find(type);
3736 /* If there is no driver for this type, ignore it. */
3740 technology_apply_rfkill_change(technology, softblock, hardblock,
3743 if (technology->hardblocked)
3744 DBG("%s hardblocked", get_name(technology->type));
3746 DBG("%s is%s softblocked", get_name(technology->type),
3747 technology->softblocked ? "" : " not");
3752 int __connman_technology_remove_rfkill(unsigned int index,
3753 enum connman_service_type type)
3755 struct connman_technology *technology;
3756 struct connman_rfkill *rfkill;
3758 DBG("index %u", index);
3760 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3764 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
3766 technology = technology_find(type);
3770 technology_apply_rfkill_change(technology,
3771 technology->softblocked, !technology->hardblocked, false);
3773 technology_put(technology);
3778 int __connman_technology_init(void)
3782 connection = connman_dbus_get_connection();
3784 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
3787 global_offlinemode = connman_technology_load_offlinemode();
3789 /* This will create settings file if it is missing */
3790 connman_technology_save_offlinemode();
3795 void __connman_technology_cleanup(void)
3799 while (technology_list) {
3800 struct connman_technology *technology = technology_list->data;
3801 technology_list = g_slist_remove(technology_list, technology);
3802 technology_put(technology);
3805 g_hash_table_destroy(rfkill_list);
3807 dbus_connection_unref(connection);