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;
83 bool tethering_hidden;
85 bool enable_persistent; /* Save the tech state */
89 DBusMessage *pending_reply;
90 guint pending_timeout;
100 static GSList *driver_list = NULL;
102 static int technology_enabled(struct connman_technology *technology);
103 static int technology_disabled(struct connman_technology *technology);
105 static gint compare_priority(gconstpointer a, gconstpointer b)
107 const struct connman_technology_driver *driver1 = a;
108 const struct connman_technology_driver *driver2 = b;
110 return driver2->priority - driver1->priority;
113 static void rfkill_check(gpointer key, gpointer value, gpointer user_data)
115 struct connman_rfkill *rfkill = value;
116 enum connman_service_type type = GPOINTER_TO_INT(user_data);
118 /* Calling _technology_rfkill_add will update the tech. */
119 if (rfkill->type == type)
120 __connman_technology_add_rfkill(rfkill->index, type,
121 rfkill->softblock, rfkill->hardblock);
125 connman_technology_is_tethering_allowed(enum connman_service_type type)
127 static char *allowed_default[] = { "wifi", "bluetooth", "gadget",
129 const char *type_str = __connman_service_type2string(type);
136 allowed = connman_setting_get_string_list("TetheringTechnologies");
138 allowed = allowed_default;
140 for (i = 0; allowed[i]; i++) {
141 if (g_strcmp0(allowed[i], type_str) == 0)
148 static const char *get_name(enum connman_service_type type)
151 case CONNMAN_SERVICE_TYPE_UNKNOWN:
152 case CONNMAN_SERVICE_TYPE_SYSTEM:
153 case CONNMAN_SERVICE_TYPE_GPS:
154 case CONNMAN_SERVICE_TYPE_VPN:
156 case CONNMAN_SERVICE_TYPE_GADGET:
158 case CONNMAN_SERVICE_TYPE_ETHERNET:
160 case CONNMAN_SERVICE_TYPE_WIFI:
162 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
164 case CONNMAN_SERVICE_TYPE_CELLULAR:
166 case CONNMAN_SERVICE_TYPE_P2P:
173 static void technology_save(struct connman_technology *technology)
177 const char *name = get_name(technology->type);
179 DBG("technology %p type %d name %s", technology, technology->type,
184 keyfile = __connman_storage_load_global();
186 keyfile = g_key_file_new();
188 identifier = g_strdup_printf("%s", name);
192 g_key_file_set_boolean(keyfile, identifier, "Enable",
193 technology->enable_persistent);
195 g_key_file_set_boolean(keyfile, identifier, "Tethering",
196 technology->tethering_persistent);
198 g_key_file_set_boolean(keyfile, identifier, "Hidden",
199 technology->tethering_hidden);
201 if (technology->tethering_ident)
202 g_key_file_set_string(keyfile, identifier,
203 "Tethering.Identifier",
204 technology->tethering_ident);
206 if (technology->tethering_passphrase)
207 g_key_file_set_string(keyfile, identifier,
208 "Tethering.Passphrase",
209 technology->tethering_passphrase);
214 __connman_storage_save_global(keyfile);
216 g_key_file_free(keyfile);
221 static void tethering_changed(struct connman_technology *technology)
223 dbus_bool_t tethering = technology->tethering;
225 connman_dbus_property_changed_basic(technology->path,
226 CONNMAN_TECHNOLOGY_INTERFACE, "Tethering",
227 DBUS_TYPE_BOOLEAN, &tethering);
229 technology_save(technology);
232 int connman_technology_tethering_notify(struct connman_technology *technology,
237 DBG("technology %p enabled %u", technology, enabled);
239 if (technology->tethering == enabled)
243 err = __connman_tethering_set_enabled();
247 __connman_tethering_set_disabled();
249 technology->tethering = enabled;
250 tethering_changed(technology);
255 static int set_tethering(struct connman_technology *technology,
258 int result = -EOPNOTSUPP;
260 const char *ident, *passphrase, *bridge;
261 GSList *tech_drivers;
263 ident = technology->tethering_ident;
264 passphrase = technology->tethering_passphrase;
266 __sync_synchronize();
267 if (!technology->enabled)
270 bridge = __connman_tethering_get_bridge();
274 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI && (!ident))
277 for (tech_drivers = technology->driver_list; tech_drivers;
278 tech_drivers = g_slist_next(tech_drivers)) {
279 struct connman_technology_driver *driver = tech_drivers->data;
281 if (!driver || !driver->set_tethering)
284 err = driver->set_tethering(technology, ident, passphrase,
287 if (result == -EINPROGRESS)
290 if (err == -EINPROGRESS || err == 0)
297 void connman_technology_regdom_notify(struct connman_technology *technology,
303 connman_error("Failed to set regulatory domain");
305 DBG("Regulatory domain set to %s", alpha2);
307 g_free(technology->regdom);
308 technology->regdom = g_strdup(alpha2);
311 static int set_regdom_by_device(struct connman_technology *technology,
316 for (list = technology->device_list; list; list = list->next) {
317 struct connman_device *device = list->data;
319 if (connman_device_set_regdom(device, alpha2) != 0)
326 int connman_technology_set_regdom(const char *alpha2)
328 GSList *list, *tech_drivers;
330 for (list = technology_list; list; list = list->next) {
331 struct connman_technology *technology = list->data;
333 if (set_regdom_by_device(technology, alpha2) != 0) {
335 for (tech_drivers = technology->driver_list;
337 tech_drivers = g_slist_next(tech_drivers)) {
339 struct connman_technology_driver *driver =
342 if (driver->set_regdom)
343 driver->set_regdom(technology, alpha2);
351 static struct connman_technology *technology_find(enum connman_service_type type)
355 DBG("type %d", type);
357 for (list = technology_list; list; list = list->next) {
358 struct connman_technology *technology = list->data;
360 if (technology->type == type)
367 bool connman_technology_get_wifi_tethering(const char **ssid,
370 struct connman_technology *technology;
377 technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
381 if (!technology->tethering)
384 *ssid = technology->tethering_ident;
385 *psk = technology->tethering_passphrase;
390 static void free_rfkill(gpointer data)
392 struct connman_rfkill *rfkill = data;
397 static void technology_load(struct connman_technology *technology)
401 GError *error = NULL;
402 bool enable, need_saving = false;
404 DBG("technology %p", technology);
406 keyfile = __connman_storage_load_global();
407 /* Fallback on disabling technology if file not found. */
409 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
410 /* We enable ethernet by default */
411 technology->enable_persistent = true;
413 technology->enable_persistent = false;
417 identifier = g_strdup_printf("%s", get_name(technology->type));
421 enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error);
423 technology->enable_persistent = enable;
425 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
426 technology->enable_persistent = true;
428 technology->enable_persistent = false;
431 g_clear_error(&error);
434 enable = g_key_file_get_boolean(keyfile, identifier,
435 "Tethering", &error);
437 technology->tethering_persistent = enable;
440 g_clear_error(&error);
444 technology_save(technology);
446 technology->tethering_ident = g_key_file_get_string(keyfile,
447 identifier, "Tethering.Identifier", NULL);
449 technology->tethering_passphrase = g_key_file_get_string(keyfile,
450 identifier, "Tethering.Passphrase", NULL);
454 g_key_file_free(keyfile);
459 bool __connman_technology_get_offlinemode(void)
461 return global_offlinemode;
464 static void connman_technology_save_offlinemode(void)
467 GError *error = NULL;
470 keyfile = __connman_storage_load_global();
473 keyfile = g_key_file_new();
474 g_key_file_set_boolean(keyfile, "global",
475 "OfflineMode", global_offlinemode);
477 __connman_storage_save_global(keyfile);
480 offlinemode = g_key_file_get_boolean(keyfile, "global",
481 "OfflineMode", &error);
483 if (error || offlinemode != global_offlinemode) {
484 g_key_file_set_boolean(keyfile, "global",
485 "OfflineMode", global_offlinemode);
487 g_clear_error(&error);
489 __connman_storage_save_global(keyfile);
493 g_key_file_free(keyfile);
498 static bool connman_technology_load_offlinemode(void)
501 GError *error = NULL;
504 /* If there is a error, we enable offlinemode */
505 keyfile = __connman_storage_load_global();
509 offlinemode = g_key_file_get_boolean(keyfile, "global",
510 "OfflineMode", &error);
513 g_clear_error(&error);
516 g_key_file_free(keyfile);
521 static void append_properties(DBusMessageIter *iter,
522 struct connman_technology *technology)
524 DBusMessageIter dict;
528 connman_dbus_dict_open(iter, &dict);
530 str = get_name(technology->type);
532 connman_dbus_dict_append_basic(&dict, "Name",
533 DBUS_TYPE_STRING, &str);
535 str = __connman_service_type2string(technology->type);
537 connman_dbus_dict_append_basic(&dict, "Type",
538 DBUS_TYPE_STRING, &str);
540 __sync_synchronize();
541 val = technology->enabled;
542 connman_dbus_dict_append_basic(&dict, "Powered",
546 val = technology->connected;
547 connman_dbus_dict_append_basic(&dict, "Connected",
551 val = technology->tethering;
552 connman_dbus_dict_append_basic(&dict, "Tethering",
556 if (technology->tethering_ident)
557 connman_dbus_dict_append_basic(&dict, "TetheringIdentifier",
559 &technology->tethering_ident);
561 if (technology->tethering_passphrase)
562 connman_dbus_dict_append_basic(&dict, "TetheringPassphrase",
564 &technology->tethering_passphrase);
566 val = technology->tethering_hidden;
567 connman_dbus_dict_append_basic(&dict, "Hidden",
571 connman_dbus_dict_close(iter, &dict);
574 static void technology_added_signal(struct connman_technology *technology)
577 DBusMessageIter iter;
579 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
580 CONNMAN_MANAGER_INTERFACE, "TechnologyAdded");
584 dbus_message_iter_init_append(signal, &iter);
585 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
587 append_properties(&iter, technology);
589 dbus_connection_send(connection, signal, NULL);
590 dbus_message_unref(signal);
593 static void technology_removed_signal(struct connman_technology *technology)
595 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
596 CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
597 DBUS_TYPE_OBJECT_PATH, &technology->path,
601 static DBusMessage *get_properties(DBusConnection *conn,
602 DBusMessage *message, void *user_data)
604 struct connman_technology *technology = user_data;
606 DBusMessageIter iter;
608 reply = dbus_message_new_method_return(message);
612 dbus_message_iter_init_append(reply, &iter);
613 append_properties(&iter, technology);
618 void __connman_technology_list_struct(DBusMessageIter *array)
621 DBusMessageIter entry;
623 for (list = technology_list; list; list = list->next) {
624 struct connman_technology *technology = list->data;
626 if (!technology->path ||
627 (technology->rfkill_driven &&
628 technology->hardblocked))
631 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
633 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
635 append_properties(&entry, technology);
636 dbus_message_iter_close_container(array, &entry);
640 static gboolean technology_pending_reply(gpointer user_data)
642 struct connman_technology *technology = user_data;
645 /* Power request timedout, send ETIMEDOUT. */
646 if (technology->pending_reply) {
647 reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
649 g_dbus_send_message(connection, reply);
651 dbus_message_unref(technology->pending_reply);
652 technology->pending_reply = NULL;
653 technology->pending_timeout = 0;
659 static int technology_affect_devices(struct connman_technology *technology,
662 int err = 0, err_dev;
665 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
667 __connman_technology_enabled(technology->type);
669 __connman_technology_disabled(technology->type);
673 for (list = technology->device_list; list; list = list->next) {
674 struct connman_device *device = list->data;
677 err_dev = __connman_device_enable(device);
679 err_dev = __connman_device_disable(device);
681 if (err_dev < 0 && err_dev != -EALREADY)
688 static void powered_changed(struct connman_technology *technology)
692 if (!technology->dbus_registered)
695 if (technology->pending_reply) {
696 g_dbus_send_reply(connection,
697 technology->pending_reply, DBUS_TYPE_INVALID);
698 dbus_message_unref(technology->pending_reply);
699 technology->pending_reply = NULL;
701 g_source_remove(technology->pending_timeout);
702 technology->pending_timeout = 0;
705 __sync_synchronize();
706 enabled = technology->enabled;
707 #if defined TIZEN_EXT
708 DBG("ConnMan, Powered : %s, %s",
709 enabled ? "TRUE" : "FALSE",technology->path);
711 connman_dbus_property_changed_basic(technology->path,
712 CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
713 DBUS_TYPE_BOOLEAN, &enabled);
716 static void enable_tethering(struct connman_technology *technology)
720 if (!connman_setting_get_bool("PersistentTetheringMode"))
723 ret = set_tethering(technology, true);
724 if (ret < 0 && ret != -EALREADY)
725 DBG("Cannot enable tethering yet for %s (%d/%s)",
726 get_name(technology->type),
727 -ret, strerror(-ret));
730 static int technology_enabled(struct connman_technology *technology)
732 __sync_synchronize();
733 if (technology->enabled)
736 technology->enabled = true;
738 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
739 struct connman_technology *p2p;
741 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
742 if (p2p && !p2p->enabled && p2p->enable_persistent)
743 technology_enabled(p2p);
746 if (technology->tethering_persistent)
747 enable_tethering(technology);
749 powered_changed(technology);
754 static int technology_enable(struct connman_technology *technology)
759 DBG("technology %p enable", technology);
761 __sync_synchronize();
763 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
764 struct connman_technology *wifi;
766 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
767 if (wifi && wifi->enabled)
768 return technology_enabled(technology);
772 if (technology->enabled)
775 if (technology->pending_reply)
778 if (connman_setting_get_bool("PersistentTetheringMode") &&
779 technology->tethering)
780 set_tethering(technology, true);
782 if (technology->rfkill_driven)
783 err = __connman_rfkill_block(technology->type, false);
785 err_dev = technology_affect_devices(technology, true);
787 if (!technology->rfkill_driven)
793 static int technology_disabled(struct connman_technology *technology)
795 __sync_synchronize();
796 if (!technology->enabled)
799 technology->enabled = false;
801 powered_changed(technology);
806 static int technology_disable(struct connman_technology *technology)
810 DBG("technology %p disable", technology);
812 __sync_synchronize();
814 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
815 technology->enable_persistent = false;
816 return technology_disabled(technology);
817 } else if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
818 struct connman_technology *p2p;
820 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
821 if (p2p && p2p->enabled) {
822 p2p->enable_persistent = true;
823 technology_disabled(p2p);
827 if (!technology->enabled)
830 if (technology->pending_reply)
833 if (technology->tethering)
834 set_tethering(technology, false);
836 err = technology_affect_devices(technology, false);
838 if (technology->rfkill_driven)
839 err = __connman_rfkill_block(technology->type, true);
844 static DBusMessage *set_powered(struct connman_technology *technology,
845 DBusMessage *msg, bool powered)
847 DBusMessage *reply = NULL;
850 if (technology->rfkill_driven && technology->hardblocked) {
856 err = technology_enable(technology);
858 err = technology_disable(technology);
861 technology->enable_persistent = powered;
862 technology_save(technology);
866 if (err == -EINPROGRESS) {
867 technology->pending_reply = dbus_message_ref(msg);
868 technology->pending_timeout = g_timeout_add_seconds(10,
869 technology_pending_reply, technology);
870 } else if (err == -EALREADY) {
872 reply = __connman_error_already_enabled(msg);
874 reply = __connman_error_already_disabled(msg);
876 reply = __connman_error_failed(msg, -err);
878 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
883 #if defined TIZEN_EXT
884 int set_connman_bssid(enum bssid_type mode, char *bssid)
886 static unsigned char bssid_for_connect[6];
887 static int bssid_len;
889 DBG("mode : %d", mode);
891 if (mode == CHECK_BSSID) {
895 if (mode == GET_BSSID && bssid) {
896 memcpy(bssid, bssid_for_connect, 6);
900 if (mode == RESET_BSSID) {
905 if (mode != SET_BSSID || !bssid) {
906 DBG("Invalid parameter");
910 bssid_len = sscanf(bssid, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
911 &bssid_for_connect[0], &bssid_for_connect[1], &bssid_for_connect[2],
912 &bssid_for_connect[3], &bssid_for_connect[4], &bssid_for_connect[5]);
913 if (bssid_len != 6) {
914 DBG("Incorrect BSSID format. bssid_len = %d", bssid_len);
918 DBG("SET BSSID len : %d, BSSID : %02x:%02x:%02x:%02x:%02x:%02x", bssid_len,
919 bssid_for_connect[0], bssid_for_connect[1], bssid_for_connect[2],
920 bssid_for_connect[3], bssid_for_connect[4], bssid_for_connect[5]);
926 static DBusMessage *set_property(DBusConnection *conn,
927 DBusMessage *msg, void *data)
929 struct connman_technology *technology = data;
930 DBusMessageIter iter, value;
934 DBG("conn %p", conn);
936 if (!dbus_message_iter_init(msg, &iter))
937 return __connman_error_invalid_arguments(msg);
939 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
940 return __connman_error_invalid_arguments(msg);
942 dbus_message_iter_get_basic(&iter, &name);
943 dbus_message_iter_next(&iter);
945 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
946 return __connman_error_invalid_arguments(msg);
948 dbus_message_iter_recurse(&iter, &value);
950 type = dbus_message_iter_get_arg_type(&value);
952 DBG("property %s", name);
954 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI && technology->connected) {
956 if (connman_dbus_get_connection_unix_user_sync(conn,
957 dbus_message_get_sender(msg),
959 DBG("Can not get unix user id!");
960 return __connman_error_permission_denied(msg);
963 if (!__connman_service_is_user_allowed(CONNMAN_SERVICE_TYPE_WIFI, uid)) {
964 DBG("Not allow this user to operate wifi technology now!");
965 return __connman_error_permission_denied(msg);
969 if (g_str_equal(name, "Tethering")) {
970 dbus_bool_t tethering;
973 if (type != DBUS_TYPE_BOOLEAN)
974 return __connman_error_invalid_arguments(msg);
976 if (!connman_technology_is_tethering_allowed(technology->type)) {
977 DBG("%s tethering not allowed by config file",
978 __connman_service_type2string(technology->type));
979 return __connman_error_not_supported(msg);
982 dbus_message_iter_get_basic(&value, &tethering);
984 if (technology->tethering == tethering) {
986 return __connman_error_already_disabled(msg);
988 return __connman_error_already_enabled(msg);
991 err = set_tethering(technology, tethering);
993 return __connman_error_failed(msg, -err);
995 technology->tethering_persistent = tethering;
997 technology_save(technology);
999 } else if (g_str_equal(name, "TetheringIdentifier")) {
1002 dbus_message_iter_get_basic(&value, &str);
1004 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1005 return __connman_error_not_supported(msg);
1007 if (strlen(str) < 1 || strlen(str) > 32)
1008 return __connman_error_invalid_arguments(msg);
1010 if (g_strcmp0(technology->tethering_ident, str) != 0) {
1011 g_free(technology->tethering_ident);
1012 technology->tethering_ident = g_strdup(str);
1013 technology_save(technology);
1015 connman_dbus_property_changed_basic(technology->path,
1016 CONNMAN_TECHNOLOGY_INTERFACE,
1017 "TetheringIdentifier",
1019 &technology->tethering_ident);
1021 } else if (g_str_equal(name, "TetheringPassphrase")) {
1024 dbus_message_iter_get_basic(&value, &str);
1026 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1027 return __connman_error_not_supported(msg);
1029 err = __connman_service_check_passphrase(CONNMAN_SERVICE_SECURITY_PSK,
1032 return __connman_error_passphrase_required(msg);
1034 if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
1035 g_free(technology->tethering_passphrase);
1036 technology->tethering_passphrase = g_strdup(str);
1037 technology_save(technology);
1039 connman_dbus_property_changed_basic(technology->path,
1040 CONNMAN_TECHNOLOGY_INTERFACE,
1041 "TetheringPassphrase",
1043 &technology->tethering_passphrase);
1045 } else if (g_str_equal(name, "Hidden")) {
1048 if (type != DBUS_TYPE_BOOLEAN)
1049 return __connman_error_invalid_arguments(msg);
1051 dbus_message_iter_get_basic(&value, &hidden);
1053 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1054 return __connman_error_not_supported(msg);
1056 technology->tethering_hidden = hidden;
1057 technology_save(technology);
1059 connman_dbus_property_changed_basic(technology->path,
1060 CONNMAN_TECHNOLOGY_INTERFACE,
1064 } else if (g_str_equal(name, "Powered")) {
1067 if (type != DBUS_TYPE_BOOLEAN)
1068 return __connman_error_invalid_arguments(msg);
1070 dbus_message_iter_get_basic(&value, &enable);
1072 return set_powered(technology, msg, enable);
1073 #if defined TIZEN_EXT
1074 } else if (g_str_equal(name, "SetBSSID")) {
1077 if (type != DBUS_TYPE_STRING)
1078 return __connman_error_invalid_arguments(msg);
1080 dbus_message_iter_get_basic(&value, &key);
1081 DBG("BSSID %s", key);
1082 set_connman_bssid(SET_BSSID, key);
1085 return __connman_error_invalid_property(msg);
1087 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1090 static void reply_scan_pending(struct connman_technology *technology, int err)
1094 DBG("technology %p err %d", technology, err);
1096 while (technology->scan_pending) {
1097 DBusMessage *msg = technology->scan_pending->data;
1099 DBG("reply to %s", dbus_message_get_sender(msg));
1102 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1104 reply = __connman_error_failed(msg, -err);
1105 g_dbus_send_message(connection, reply);
1106 dbus_message_unref(msg);
1108 technology->scan_pending =
1109 g_slist_delete_link(technology->scan_pending,
1110 technology->scan_pending);
1114 #if defined TIZEN_EXT
1115 dbus_bool_t __connman_technology_notify_scan_changed(const char *key, void *val)
1118 DBusMessage *signal;
1119 DBusMessageIter iter;
1120 dbus_bool_t result = FALSE;
1122 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1123 CONNMAN_MANAGER_INTERFACE, "ScanChanged");
1127 dbus_message_iter_init_append(signal, &iter);
1128 connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_BOOLEAN, val);
1130 result = dbus_connection_send(connection, signal, NULL);
1131 dbus_message_unref(signal);
1133 DBG("Successfuly sent signal");
1139 void __connman_technology_scan_started(struct connman_device *device)
1141 DBG("device %p", device);
1142 #if defined TIZEN_EXT
1143 dbus_bool_t status = 1;
1144 __connman_technology_notify_scan_changed("scan_started", &status);
1148 void __connman_technology_scan_stopped(struct connman_device *device,
1149 enum connman_service_type type)
1152 struct connman_technology *technology;
1155 technology = technology_find(type);
1157 DBG("technology %p device %p", technology, device);
1162 for (list = technology->device_list; list; list = list->next) {
1163 struct connman_device *other_device = list->data;
1165 if (device == other_device)
1168 if (__connman_device_get_service_type(other_device) != type)
1171 if (connman_device_get_scanning(other_device))
1175 #if defined TIZEN_EXT
1177 DBusMessage *signal;
1178 DBusMessageIter iter;
1179 dbus_bool_t status = 0;
1180 __connman_technology_notify_scan_changed("scan_done", &status);
1182 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1183 CONNMAN_MANAGER_INTERFACE, "ScanDone");
1187 dbus_message_iter_init_append(signal, &iter);
1188 connman_dbus_property_append_basic(&iter, "Scantype",
1189 DBUS_TYPE_INT32, &g_scan_type);
1191 dbus_connection_send(connection, signal, NULL);
1192 dbus_message_unref(signal);
1193 reply_scan_pending(technology, 0);
1195 DBG("Successfuly sent ScanDone signal");
1199 reply_scan_pending(technology, 0);
1203 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
1204 int result, const char *alpha2)
1206 bool regdom_set = false;
1207 struct connman_technology *technology;
1208 enum connman_service_type type;
1209 GSList *tech_drivers;
1211 type = __connman_device_get_service_type(device);
1212 technology = technology_find(type);
1219 for (tech_drivers = technology->driver_list;
1221 tech_drivers = g_slist_next(tech_drivers)) {
1222 struct connman_technology_driver *driver =
1225 if (driver->set_regdom) {
1226 driver->set_regdom(technology, alpha2);
1236 connman_technology_regdom_notify(technology, alpha2);
1239 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
1241 struct connman_technology *technology = data;
1244 DBG("technology %p request from %s", technology,
1245 dbus_message_get_sender(msg));
1247 if (technology->type == CONNMAN_SERVICE_TYPE_P2P &&
1248 !technology->enabled)
1249 return __connman_error_permission_denied(msg);
1251 dbus_message_ref(msg);
1252 #if !defined TIZEN_EXT
1253 technology->scan_pending =
1254 g_slist_prepend(technology->scan_pending, msg);
1257 err = __connman_device_request_scan(technology->type);
1258 #if defined TIZEN_EXT
1260 return __connman_error_failed(msg, -err);
1263 reply_scan_pending(technology, err);
1266 #if defined TIZEN_EXT
1268 g_scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1269 DBG("g_scan_type %d", g_scan_type);
1271 technology->scan_pending =
1272 g_slist_prepend(technology->scan_pending, msg);
1277 #if defined TIZEN_EXT
1278 static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void *data)
1280 struct connman_technology *technology = data;
1281 GSList *specific_scan_list = NULL;
1283 const char *name = NULL;
1284 const char *freq = NULL;
1285 DBusMessageIter iter, dict;
1288 DBG("technology %p request from %s", technology,
1289 dbus_message_get_sender(msg));
1291 if (!dbus_message_iter_init(msg, &iter))
1292 return __connman_error_invalid_arguments(msg);
1294 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1295 return __connman_error_invalid_arguments(msg);
1297 dbus_message_iter_recurse(&iter, &dict);
1298 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1299 DBusMessageIter entry, value2;
1303 dbus_message_iter_recurse(&dict, &entry);
1304 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) {
1305 g_slist_free_full(specific_scan_list, g_free);
1306 return __connman_error_invalid_arguments(msg);
1309 dbus_message_iter_get_basic(&entry, &key);
1310 dbus_message_iter_next(&entry);
1312 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) {
1313 g_slist_free_full(specific_scan_list, g_free);
1314 return __connman_error_invalid_arguments(msg);
1317 dbus_message_iter_recurse(&entry, &value2);
1318 type = dbus_message_iter_get_arg_type(&value2);
1319 if (g_str_equal(key, "SSID")) {
1320 if (type != DBUS_TYPE_STRING) {
1321 g_slist_free_full(specific_scan_list, g_free);
1322 return __connman_error_invalid_arguments(msg);
1325 scan_type = CONNMAN_MULTI_SCAN_SSID; /* SSID based scan */
1326 dbus_message_iter_get_basic(&value2, &name);
1327 DBG("name %s", name);
1328 specific_scan_list = g_slist_append(specific_scan_list, g_strdup(name));
1329 } else if (g_str_equal(key, "Frequency")) {
1330 if (type != DBUS_TYPE_STRING) {
1331 g_slist_free_full(specific_scan_list, g_free);
1332 return __connman_error_invalid_arguments(msg);
1335 scan_type = CONNMAN_MULTI_SCAN_FREQ; /* Frequency based scan */
1336 dbus_message_iter_get_basic(&value2, &freq);
1337 DBG("freq %s", freq);
1338 specific_scan_list = g_slist_append(specific_scan_list, GINT_TO_POINTER(atoi(freq)));
1339 } else if (g_str_equal(key, "SSID_Mixed")) {
1340 if (type != DBUS_TYPE_STRING) {
1341 g_slist_free_full(specific_scan_list, g_free);
1342 return __connman_error_invalid_arguments(msg);
1345 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1346 dbus_message_iter_get_basic(&value2, &name);
1348 connman_multi_scan_ap_s *ap = (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1350 g_strlcpy(ap->str, name, strlen(name) + 1);
1352 specific_scan_list = g_slist_append(specific_scan_list, ap);
1354 DBG("Failed to allocate memory");
1356 } else if (g_str_equal(key, "Frequency_Mixed")) {
1357 if (type != DBUS_TYPE_STRING) {
1358 g_slist_free_full(specific_scan_list, g_free);
1359 return __connman_error_invalid_arguments(msg);
1362 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1363 dbus_message_iter_get_basic(&value2, &freq);
1365 connman_multi_scan_ap_s *ap = (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1367 g_strlcpy(ap->str, freq, strlen(freq) + 1);
1369 specific_scan_list = g_slist_append(specific_scan_list, ap);
1371 DBG("Failed to allocate memory");
1373 dbus_message_iter_next(&dict);
1376 dbus_message_ref(msg);
1378 err = __connman_device_request_specific_scan(technology->type, scan_type, specific_scan_list);
1380 return __connman_error_failed(msg, -err);
1383 guint list_size = g_slist_length(specific_scan_list);
1385 g_scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP;
1387 g_scan_type = CONNMAN_SCAN_TYPE_MULTI_AP;
1388 DBG("list_size %u g_scan_type %d", list_size, g_scan_type);
1390 technology->scan_pending =
1391 g_slist_prepend(technology->scan_pending, msg);
1393 if (scan_type == CONNMAN_MULTI_SCAN_SSID ||
1394 scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) {
1395 g_slist_free_full(specific_scan_list, g_free);
1401 static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data)
1404 DBusMessageIter iter, dict;
1406 struct connman_technology *technology = data;
1407 dbus_bool_t scanning = false;
1409 DBG("technology %p", technology);
1411 for (list = technology->device_list; list; list = list->next) {
1412 struct connman_device *device = list->data;
1413 scanning = connman_device_get_scanning(device);
1418 DBG("scanning : %d", scanning);
1419 reply = dbus_message_new_method_return(msg);
1423 dbus_message_iter_init_append(reply, &iter);
1425 connman_dbus_dict_open(&iter, &dict);
1426 connman_dbus_dict_append_basic(&dict, "Scanstate",
1430 connman_dbus_dict_close(&iter, &dict);
1436 static const GDBusMethodTable technology_methods[] = {
1437 { GDBUS_DEPRECATED_METHOD("GetProperties",
1438 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
1440 { GDBUS_ASYNC_METHOD("SetProperty",
1441 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1442 NULL, set_property) },
1443 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
1444 #if defined TIZEN_EXT
1445 { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }),
1446 NULL, specific_scan) },
1447 { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }),
1453 static const GDBusSignalTable technology_signals[] = {
1454 { GDBUS_SIGNAL("PropertyChanged",
1455 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
1456 { GDBUS_SIGNAL("DhcpConnected",
1457 GDBUS_ARGS({ "aptype", "s" },
1460 { "hostname", "s" })) },
1461 { GDBUS_SIGNAL("DhcpLeaseDeleted",
1462 GDBUS_ARGS({ "aptype", "s" },
1465 { "hostname", "s" })) },
1469 static bool technology_dbus_register(struct connman_technology *technology)
1471 if (technology->dbus_registered ||
1472 (technology->rfkill_driven &&
1473 technology->hardblocked))
1476 if (!g_dbus_register_interface(connection, technology->path,
1477 CONNMAN_TECHNOLOGY_INTERFACE,
1478 technology_methods, technology_signals,
1479 NULL, technology, NULL)) {
1480 connman_error("Failed to register %s", technology->path);
1484 technology_added_signal(technology);
1485 technology->dbus_registered = true;
1490 static void technology_dbus_unregister(struct connman_technology *technology)
1492 if (!technology->dbus_registered)
1495 technology_removed_signal(technology);
1496 g_dbus_unregister_interface(connection, technology->path,
1497 CONNMAN_TECHNOLOGY_INTERFACE);
1499 technology->dbus_registered = false;
1502 static void technology_put(struct connman_technology *technology)
1504 DBG("technology %p", technology);
1506 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
1509 reply_scan_pending(technology, -EINTR);
1511 while (technology->driver_list) {
1512 struct connman_technology_driver *driver;
1514 driver = technology->driver_list->data;
1517 driver->remove(technology);
1519 technology->driver_list =
1520 g_slist_delete_link(technology->driver_list,
1521 technology->driver_list);
1524 technology_list = g_slist_remove(technology_list, technology);
1526 technology_dbus_unregister(technology);
1528 g_slist_free(technology->device_list);
1530 if (technology->pending_reply) {
1531 dbus_message_unref(technology->pending_reply);
1532 technology->pending_reply = NULL;
1533 g_source_remove(technology->pending_timeout);
1534 technology->pending_timeout = 0;
1537 g_free(technology->path);
1538 g_free(technology->regdom);
1539 g_free(technology->tethering_ident);
1540 g_free(technology->tethering_passphrase);
1544 static struct connman_technology *technology_get(enum connman_service_type type)
1546 GSList *tech_drivers = NULL;
1547 struct connman_technology_driver *driver;
1548 struct connman_technology *technology;
1552 DBG("type %d", type);
1554 str = __connman_service_type2string(type);
1558 technology = technology_find(type);
1560 if (type != CONNMAN_SERVICE_TYPE_P2P)
1561 __sync_fetch_and_add(&technology->refcount, 1);
1565 /* First check if we have a driver for this technology type */
1566 for (list = driver_list; list; list = list->next) {
1567 driver = list->data;
1569 if (driver->type == type) {
1570 DBG("technology %p driver %p", technology, driver);
1571 tech_drivers = g_slist_append(tech_drivers, driver);
1575 if (!tech_drivers) {
1576 DBG("No matching drivers found for %s.",
1577 __connman_service_type2string(type));
1581 technology = g_try_new0(struct connman_technology, 1);
1585 technology->refcount = 1;
1586 technology->type = type;
1587 technology->tethering_hidden = FALSE;
1588 technology->path = g_strdup_printf("%s/technology/%s",
1591 technology_load(technology);
1592 technology_list = g_slist_prepend(technology_list, technology);
1593 technology->driver_list = tech_drivers;
1595 for (list = tech_drivers; list; list = list->next) {
1596 driver = list->data;
1598 if (driver->probe && driver->probe(technology) < 0)
1599 DBG("Driver probe failed for technology %p",
1603 if (!technology_dbus_register(technology)) {
1604 technology_put(technology);
1608 if (type == CONNMAN_SERVICE_TYPE_P2P) {
1609 struct connman_technology *wifi;
1612 enable = technology->enable_persistent;
1614 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
1616 enable = wifi->enabled;
1618 technology_affect_devices(technology, enable);
1621 DBG("technology %p %s", technology, get_name(technology->type));
1626 int connman_technology_driver_register(struct connman_technology_driver *driver)
1629 struct connman_device *device;
1630 enum connman_service_type type;
1632 for (list = driver_list; list; list = list->next) {
1633 if (list->data == driver)
1637 DBG("Registering %s driver", driver->name);
1639 driver_list = g_slist_insert_sorted(driver_list, driver,
1643 * Check for technology less devices if this driver
1644 * can service any of them.
1646 for (list = techless_device_list; list; list = list->next) {
1647 device = list->data;
1649 type = __connman_device_get_service_type(device);
1650 if (type != driver->type)
1653 techless_device_list = g_slist_remove(techless_device_list,
1656 __connman_technology_add_device(device);
1659 /* Check for orphaned rfkill switches. */
1660 g_hash_table_foreach(rfkill_list, rfkill_check,
1661 GINT_TO_POINTER(driver->type));
1664 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
1665 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
1672 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
1674 GSList *list, *tech_drivers;
1675 struct connman_technology *technology;
1676 struct connman_technology_driver *current;
1678 DBG("Unregistering driver %p name %s", driver, driver->name);
1680 for (list = technology_list; list; list = list->next) {
1681 technology = list->data;
1683 for (tech_drivers = technology->driver_list; tech_drivers;
1684 tech_drivers = g_slist_next(tech_drivers)) {
1685 current = tech_drivers->data;
1686 if (driver != current)
1690 driver->remove(technology);
1692 technology->driver_list =
1693 g_slist_remove(technology->driver_list,
1699 driver_list = g_slist_remove(driver_list, driver);
1701 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
1702 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
1704 technology_put(technology);
1708 void __connman_technology_add_interface(enum connman_service_type type,
1709 int index, const char *ident)
1711 struct connman_technology *technology;
1712 GSList *tech_drivers;
1713 struct connman_technology_driver *driver;
1717 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1718 case CONNMAN_SERVICE_TYPE_SYSTEM:
1720 case CONNMAN_SERVICE_TYPE_ETHERNET:
1721 case CONNMAN_SERVICE_TYPE_WIFI:
1722 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1723 case CONNMAN_SERVICE_TYPE_CELLULAR:
1724 case CONNMAN_SERVICE_TYPE_GPS:
1725 case CONNMAN_SERVICE_TYPE_VPN:
1726 case CONNMAN_SERVICE_TYPE_GADGET:
1727 case CONNMAN_SERVICE_TYPE_P2P:
1731 name = connman_inet_ifname(index);
1732 connman_info("Adding interface %s [ %s ]", name,
1733 __connman_service_type2string(type));
1735 technology = technology_find(type);
1740 for (tech_drivers = technology->driver_list; tech_drivers;
1741 tech_drivers = g_slist_next(tech_drivers)) {
1742 driver = tech_drivers->data;
1744 if (driver->add_interface)
1745 driver->add_interface(technology, index, name, ident);
1749 * At this point we can try to enable tethering automatically as
1750 * now the interfaces are set properly.
1752 if (technology->tethering_persistent)
1753 enable_tethering(technology);
1759 void __connman_technology_remove_interface(enum connman_service_type type,
1760 int index, const char *ident)
1762 struct connman_technology *technology;
1763 GSList *tech_drivers;
1764 struct connman_technology_driver *driver;
1768 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1769 case CONNMAN_SERVICE_TYPE_SYSTEM:
1771 case CONNMAN_SERVICE_TYPE_ETHERNET:
1772 case CONNMAN_SERVICE_TYPE_WIFI:
1773 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1774 case CONNMAN_SERVICE_TYPE_CELLULAR:
1775 case CONNMAN_SERVICE_TYPE_GPS:
1776 case CONNMAN_SERVICE_TYPE_VPN:
1777 case CONNMAN_SERVICE_TYPE_GADGET:
1778 case CONNMAN_SERVICE_TYPE_P2P:
1782 name = connman_inet_ifname(index);
1783 connman_info("Remove interface %s [ %s ]", name,
1784 __connman_service_type2string(type));
1787 technology = technology_find(type);
1792 for (tech_drivers = technology->driver_list; tech_drivers;
1793 tech_drivers = g_slist_next(tech_drivers)) {
1794 driver = tech_drivers->data;
1796 if (driver->remove_interface)
1797 driver->remove_interface(technology, index);
1801 int __connman_technology_add_device(struct connman_device *device)
1803 struct connman_technology *technology;
1804 enum connman_service_type type;
1806 type = __connman_device_get_service_type(device);
1808 DBG("device %p type %s", device, get_name(type));
1810 technology = technology_get(type);
1813 * Since no driver can be found for this device at the moment we
1814 * add it to the techless device list.
1816 techless_device_list = g_slist_prepend(techless_device_list,
1822 __sync_synchronize();
1823 if (technology->rfkill_driven) {
1824 if (technology->enabled)
1825 __connman_device_enable(device);
1827 __connman_device_disable(device);
1832 if (technology->enable_persistent &&
1833 !global_offlinemode) {
1834 int err = __connman_device_enable(device);
1836 * connman_technology_add_device() calls __connman_device_enable()
1837 * but since the device is already enabled, the calls does not
1838 * propagate through to connman_technology_enabled via
1839 * connman_device_set_powered.
1841 if (err == -EALREADY)
1842 __connman_technology_enabled(type);
1844 /* if technology persistent state is offline */
1845 if (!technology->enable_persistent)
1846 __connman_device_disable(device);
1849 technology->device_list = g_slist_prepend(technology->device_list,
1855 int __connman_technology_remove_device(struct connman_device *device)
1857 struct connman_technology *technology;
1858 enum connman_service_type type;
1860 DBG("device %p", device);
1862 type = __connman_device_get_service_type(device);
1864 technology = technology_find(type);
1866 techless_device_list = g_slist_remove(techless_device_list,
1871 technology->device_list = g_slist_remove(technology->device_list,
1874 if (technology->tethering)
1875 set_tethering(technology, false);
1877 technology_put(technology);
1882 int __connman_technology_enabled(enum connman_service_type type)
1884 struct connman_technology *technology;
1886 technology = technology_find(type);
1890 DBG("technology %p type %s rfkill %d enabled %d", technology,
1891 get_name(type), technology->rfkill_driven,
1892 technology->enabled);
1893 #if !defined TIZEN_EXT
1894 if (technology->rfkill_driven) {
1895 if (technology->tethering_persistent)
1896 enable_tethering(technology);
1901 return technology_enabled(technology);
1904 int __connman_technology_disabled(enum connman_service_type type)
1906 struct connman_technology *technology;
1909 technology = technology_find(type);
1912 #if !defined TIZEN_EXT
1913 if (technology->rfkill_driven)
1916 for (list = technology->device_list; list; list = list->next) {
1917 struct connman_device *device = list->data;
1919 if (connman_device_get_powered(device))
1923 return technology_disabled(technology);
1926 int __connman_technology_set_offlinemode(bool offlinemode)
1929 int err = -EINVAL, enabled_tech_count = 0;
1931 if (global_offlinemode == offlinemode)
1934 DBG("offlinemode %s", offlinemode ? "On" : "Off");
1937 * This is a bit tricky. When you set offlinemode, there is no
1938 * way to differentiate between attempting offline mode and
1939 * resuming offlinemode from last saved profile. We need that
1940 * information in rfkill_update, otherwise it falls back on the
1941 * technology's persistent state. Hence we set the offline mode here
1942 * but save it & call the notifier only if its successful.
1945 global_offlinemode = offlinemode;
1947 /* Traverse technology list, enable/disable each technology. */
1948 for (list = technology_list; list; list = list->next) {
1949 struct connman_technology *technology = list->data;
1952 err = technology_disable(technology);
1954 if (technology->hardblocked)
1957 if (technology->enable_persistent) {
1958 err = technology_enable(technology);
1959 enabled_tech_count++;
1964 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
1965 (err == -EINVAL && enabled_tech_count == 0)) {
1966 connman_technology_save_offlinemode();
1967 __connman_notifier_offlinemode(offlinemode);
1969 global_offlinemode = connman_technology_load_offlinemode();
1974 void __connman_technology_set_connected(enum connman_service_type type,
1977 struct connman_technology *technology;
1980 technology = technology_find(type);
1984 DBG("technology %p connected %d", technology, connected);
1986 technology->connected = connected;
1989 connman_dbus_property_changed_basic(technology->path,
1990 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
1991 DBUS_TYPE_BOOLEAN, &val);
1994 static bool technology_apply_rfkill_change(struct connman_technology *technology,
1999 bool hardblock_changed = false;
2001 GList *start, *list;
2003 DBG("technology %p --> %d/%d vs %d/%d",
2004 technology, softblock, hardblock,
2005 technology->softblocked, technology->hardblocked);
2007 if (technology->hardblocked == hardblock)
2008 goto softblock_change;
2010 if (!(new_rfkill && !hardblock)) {
2011 start = g_hash_table_get_values(rfkill_list);
2013 for (list = start; list; list = list->next) {
2014 struct connman_rfkill *rfkill = list->data;
2016 if (rfkill->type != technology->type)
2019 if (rfkill->hardblock != hardblock)
2027 goto softblock_change;
2029 technology->hardblocked = hardblock;
2030 hardblock_changed = true;
2033 if (!apply && technology->softblocked != softblock)
2037 return technology->hardblocked;
2039 technology->softblocked = softblock;
2041 if (technology->hardblocked ||
2042 technology->softblocked) {
2043 if (technology_disabled(technology) != -EALREADY)
2044 technology_affect_devices(technology, false);
2045 } else if (!technology->hardblocked &&
2046 !technology->softblocked) {
2047 if (technology_enabled(technology) != -EALREADY)
2048 technology_affect_devices(technology, true);
2051 if (hardblock_changed) {
2052 if (technology->hardblocked) {
2053 DBG("%s is switched off.", get_name(technology->type));
2054 technology_dbus_unregister(technology);
2056 DBG("%s is switched on.", get_name(technology->type));
2057 technology_dbus_register(technology);
2059 if (global_offlinemode)
2060 __connman_rfkill_block(technology->type, true);
2064 return technology->hardblocked;
2067 int __connman_technology_add_rfkill(unsigned int index,
2068 enum connman_service_type type,
2072 struct connman_technology *technology;
2073 struct connman_rfkill *rfkill;
2075 DBG("index %u type %d soft %u hard %u", index, type,
2076 softblock, hardblock);
2078 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
2082 rfkill = g_try_new0(struct connman_rfkill, 1);
2086 rfkill->index = index;
2087 rfkill->type = type;
2088 rfkill->softblock = softblock;
2089 rfkill->hardblock = hardblock;
2091 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
2094 #if defined TIZEN_EXT
2095 /* Fix Svace Issue [WGID: 1348]. */
2098 technology = technology_get(type);
2099 /* If there is no driver for this type, ignore it. */
2103 technology->rfkill_driven = true;
2105 #if !defined TIZEN_EXT
2106 /* If hardblocked, there is no need to handle softblocked state */
2107 if (technology_apply_rfkill_change(technology,
2108 softblock, hardblock, true))
2111 if (global_offlinemode)
2115 * Depending on softblocked state we unblock/block according to
2116 * offlinemode and persistente state.
2118 if (technology->softblocked &&
2119 technology->enable_persistent)
2120 return __connman_rfkill_block(type, false);
2121 else if (!technology->softblocked &&
2122 !technology->enable_persistent)
2123 return __connman_rfkill_block(type, true);
2128 int __connman_technology_update_rfkill(unsigned int index,
2129 enum connman_service_type type,
2133 struct connman_technology *technology;
2134 struct connman_rfkill *rfkill;
2136 DBG("index %u soft %u hard %u", index, softblock, hardblock);
2138 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
2142 if (rfkill->softblock == softblock &&
2143 rfkill->hardblock == hardblock)
2146 rfkill->softblock = softblock;
2147 rfkill->hardblock = hardblock;
2149 technology = technology_find(type);
2150 /* If there is no driver for this type, ignore it. */
2154 technology_apply_rfkill_change(technology, softblock, hardblock,
2157 if (technology->hardblocked)
2158 DBG("%s hardblocked", get_name(technology->type));
2160 DBG("%s is%s softblocked", get_name(technology->type),
2161 technology->softblocked ? "" : " not");
2166 int __connman_technology_remove_rfkill(unsigned int index,
2167 enum connman_service_type type)
2169 struct connman_technology *technology;
2170 struct connman_rfkill *rfkill;
2172 DBG("index %u", index);
2174 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
2178 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
2180 technology = technology_find(type);
2184 technology_apply_rfkill_change(technology,
2185 technology->softblocked, !technology->hardblocked, false);
2187 technology_put(technology);
2192 int __connman_technology_init(void)
2196 connection = connman_dbus_get_connection();
2198 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
2201 global_offlinemode = connman_technology_load_offlinemode();
2203 /* This will create settings file if it is missing */
2204 connman_technology_save_offlinemode();
2209 void __connman_technology_cleanup(void)
2213 while (technology_list) {
2214 struct connman_technology *technology = technology_list->data;
2215 technology_list = g_slist_remove(technology_list, technology);
2216 technology_put(technology);
2219 g_hash_table_destroy(rfkill_list);
2221 dbus_connection_unref(connection);