5 * Copyright (C) 2007-2012 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
33 static DBusConnection *connection;
35 static GSList *technology_list = NULL;
38 * List of devices with no technology associated with them either because of
39 * no compiled in support or the driver is not yet loaded.
41 static GSList *techless_device_list = NULL;
42 static GHashTable *rfkill_list;
44 static connman_bool_t global_offlinemode;
46 struct connman_rfkill {
48 enum connman_service_type type;
49 connman_bool_t softblock;
50 connman_bool_t hardblock;
53 struct connman_technology {
55 enum connman_service_type type;
58 connman_bool_t enabled;
60 connman_bool_t connected;
62 connman_bool_t tethering;
63 char *tethering_ident;
64 char *tethering_passphrase;
66 connman_bool_t enable_persistent; /* Save the tech state */
70 DBusMessage *pending_reply;
71 guint pending_timeout;
75 connman_bool_t rfkill_driven;
76 connman_bool_t softblocked;
77 connman_bool_t hardblocked;
78 connman_bool_t dbus_registered;
81 static GSList *driver_list = NULL;
83 static gint compare_priority(gconstpointer a, gconstpointer b)
85 const struct connman_technology_driver *driver1 = a;
86 const struct connman_technology_driver *driver2 = b;
88 return driver2->priority - driver1->priority;
91 static void rfkill_check(gpointer key, gpointer value, gpointer user_data)
93 struct connman_rfkill *rfkill = value;
94 enum connman_service_type type = GPOINTER_TO_INT(user_data);
96 /* Calling _technology_rfkill_add will update the tech. */
97 if (rfkill->type == type)
98 __connman_technology_add_rfkill(rfkill->index, type,
99 rfkill->softblock, rfkill->hardblock);
103 connman_technology_is_tethering_allowed(enum connman_service_type type)
105 static char *allowed_default[] = { "wifi", "bluetooth", "gadget",
107 const char *type_str = __connman_service_type2string(type);
111 if (type_str == NULL)
114 allowed = connman_setting_get_string_list("AllowedTetheringTechnologies");
116 allowed = allowed_default;
118 for (i = 0; allowed[i] != NULL; i++) {
119 if (g_strcmp0(allowed[i], type_str) == 0)
127 * connman_technology_driver_register:
128 * @driver: Technology driver definition
130 * Register a new technology driver
132 * Returns: %0 on success
134 int connman_technology_driver_register(struct connman_technology_driver *driver)
137 struct connman_device *device;
138 enum connman_service_type type;
140 DBG("Registering %s driver", driver->name);
142 driver_list = g_slist_insert_sorted(driver_list, driver,
146 * Check for technology less devices if this driver
147 * can service any of them.
149 for (list = techless_device_list; list != NULL; list = list->next) {
152 type = __connman_device_get_service_type(device);
153 if (type != driver->type)
156 techless_device_list = g_slist_remove(techless_device_list,
159 __connman_technology_add_device(device);
162 /* Check for orphaned rfkill switches. */
163 g_hash_table_foreach(rfkill_list, rfkill_check,
164 GINT_TO_POINTER(driver->type));
170 * connman_technology_driver_unregister:
171 * @driver: Technology driver definition
173 * Remove a previously registered technology driver
175 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
177 GSList *list, *tech_drivers;
178 struct connman_technology *technology;
179 struct connman_technology_driver *current;
181 DBG("Unregistering driver %p name %s", driver, driver->name);
183 for (list = technology_list; list; list = list->next) {
184 technology = list->data;
186 for (tech_drivers = technology->driver_list;
187 tech_drivers != NULL;
188 tech_drivers = g_slist_next(tech_drivers)) {
190 current = tech_drivers->data;
191 if (driver != current)
194 if (driver->remove != NULL)
195 driver->remove(technology);
197 technology->driver_list =
198 g_slist_remove(technology->driver_list, driver);
204 driver_list = g_slist_remove(driver_list, driver);
207 static void tethering_changed(struct connman_technology *technology)
209 connman_bool_t tethering = technology->tethering;
211 connman_dbus_property_changed_basic(technology->path,
212 CONNMAN_TECHNOLOGY_INTERFACE, "Tethering",
213 DBUS_TYPE_BOOLEAN, &tethering);
216 void connman_technology_tethering_notify(struct connman_technology *technology,
217 connman_bool_t enabled)
221 DBG("technology %p enabled %u", technology, enabled);
223 if (technology->tethering == enabled)
226 technology->tethering = enabled;
228 tethering_changed(technology);
231 __connman_tethering_set_enabled();
233 for (list = technology_list; list; list = list->next) {
234 struct connman_technology *other_tech = list->data;
235 if (other_tech->tethering == TRUE)
239 __connman_tethering_set_disabled();
243 static int set_tethering(struct connman_technology *technology,
244 connman_bool_t enabled)
246 int result = -EOPNOTSUPP;
248 const char *ident, *passphrase, *bridge;
249 GSList *tech_drivers;
251 ident = technology->tethering_ident;
252 passphrase = technology->tethering_passphrase;
254 __sync_synchronize();
255 if (technology->enabled == FALSE)
258 bridge = __connman_tethering_get_bridge();
262 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI &&
263 (ident == NULL || passphrase == NULL))
266 for (tech_drivers = technology->driver_list; tech_drivers != NULL;
267 tech_drivers = g_slist_next(tech_drivers)) {
268 struct connman_technology_driver *driver = tech_drivers->data;
270 if (driver == NULL || driver->set_tethering == NULL)
273 err = driver->set_tethering(technology, ident, passphrase,
276 if (result == -EINPROGRESS)
279 if (err == -EINPROGRESS || err == 0) {
288 void connman_technology_regdom_notify(struct connman_technology *technology,
294 connman_error("Failed to set regulatory domain");
296 DBG("Regulatory domain set to %s", alpha2);
298 g_free(technology->regdom);
299 technology->regdom = g_strdup(alpha2);
302 static int set_regdom_by_device(struct connman_technology *technology,
307 for (list = technology->device_list; list; list = list->next) {
308 struct connman_device *device = list->data;
310 if (connman_device_set_regdom(device, alpha2) != 0)
317 int connman_technology_set_regdom(const char *alpha2)
319 GSList *list, *tech_drivers;
321 for (list = technology_list; list; list = list->next) {
322 struct connman_technology *technology = list->data;
324 if (set_regdom_by_device(technology, alpha2) != 0) {
326 for (tech_drivers = technology->driver_list;
327 tech_drivers != NULL;
328 tech_drivers = g_slist_next(tech_drivers)) {
330 struct connman_technology_driver *driver =
333 if (driver->set_regdom != NULL)
334 driver->set_regdom(technology, alpha2);
342 static struct connman_technology *technology_find(enum connman_service_type type)
346 DBG("type %d", type);
348 for (list = technology_list; list; list = list->next) {
349 struct connman_technology *technology = list->data;
351 if (technology->type == type)
358 connman_bool_t connman_technology_get_wifi_tethering(const char **ssid,
361 struct connman_technology *technology;
363 if (ssid == NULL || psk == NULL)
368 technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
369 if (technology == NULL)
372 if (technology->tethering == FALSE)
375 *ssid = technology->tethering_ident;
376 *psk = technology->tethering_passphrase;
381 static void free_rfkill(gpointer data)
383 struct connman_rfkill *rfkill = data;
388 static const char *get_name(enum connman_service_type type)
391 case CONNMAN_SERVICE_TYPE_UNKNOWN:
392 case CONNMAN_SERVICE_TYPE_SYSTEM:
393 case CONNMAN_SERVICE_TYPE_GPS:
394 case CONNMAN_SERVICE_TYPE_VPN:
395 case CONNMAN_SERVICE_TYPE_GADGET:
397 case CONNMAN_SERVICE_TYPE_ETHERNET:
399 case CONNMAN_SERVICE_TYPE_WIFI:
401 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
403 case CONNMAN_SERVICE_TYPE_CELLULAR:
410 static void technology_save(struct connman_technology *technology)
415 DBG("technology %p", technology);
417 keyfile = __connman_storage_load_global();
419 keyfile = g_key_file_new();
421 identifier = g_strdup_printf("%s", get_name(technology->type));
422 if (identifier == NULL)
425 g_key_file_set_boolean(keyfile, identifier, "Enable",
426 technology->enable_persistent);
428 if (technology->tethering_ident != NULL)
429 g_key_file_set_string(keyfile, identifier,
430 "Tethering.Identifier",
431 technology->tethering_ident);
433 if (technology->tethering_passphrase != NULL)
434 g_key_file_set_string(keyfile, identifier,
435 "Tethering.Passphrase",
436 technology->tethering_passphrase);
441 __connman_storage_save_global(keyfile);
443 g_key_file_free(keyfile);
448 static void technology_load(struct connman_technology *technology)
452 GError *error = NULL;
453 connman_bool_t enable;
455 DBG("technology %p", technology);
457 keyfile = __connman_storage_load_global();
458 /* Fallback on disabling technology if file not found. */
459 if (keyfile == NULL) {
460 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
461 /* We enable ethernet by default */
462 technology->enable_persistent = TRUE;
464 technology->enable_persistent = FALSE;
468 identifier = g_strdup_printf("%s", get_name(technology->type));
469 if (identifier == NULL)
472 enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error);
474 technology->enable_persistent = enable;
476 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
477 technology->enable_persistent = TRUE;
479 technology->enable_persistent = FALSE;
481 technology_save(technology);
482 g_clear_error(&error);
485 technology->tethering_ident = g_key_file_get_string(keyfile,
486 identifier, "Tethering.Identifier", NULL);
488 technology->tethering_passphrase = g_key_file_get_string(keyfile,
489 identifier, "Tethering.Passphrase", NULL);
493 g_key_file_free(keyfile);
498 connman_bool_t __connman_technology_get_offlinemode(void)
500 return global_offlinemode;
503 static void connman_technology_save_offlinemode()
507 keyfile = __connman_storage_load_global();
509 keyfile = g_key_file_new();
511 g_key_file_set_boolean(keyfile, "global",
512 "OfflineMode", global_offlinemode);
514 __connman_storage_save_global(keyfile);
516 g_key_file_free(keyfile);
521 static connman_bool_t connman_technology_load_offlinemode()
524 GError *error = NULL;
525 connman_bool_t offlinemode;
527 /* If there is a error, we enable offlinemode */
528 keyfile = __connman_storage_load_global();
532 offlinemode = g_key_file_get_boolean(keyfile, "global",
533 "OfflineMode", &error);
536 g_clear_error(&error);
539 g_key_file_free(keyfile);
544 static void append_properties(DBusMessageIter *iter,
545 struct connman_technology *technology)
547 DBusMessageIter dict;
550 connman_dbus_dict_open(iter, &dict);
552 str = get_name(technology->type);
554 connman_dbus_dict_append_basic(&dict, "Name",
555 DBUS_TYPE_STRING, &str);
557 str = __connman_service_type2string(technology->type);
559 connman_dbus_dict_append_basic(&dict, "Type",
560 DBUS_TYPE_STRING, &str);
562 __sync_synchronize();
563 connman_dbus_dict_append_basic(&dict, "Powered",
565 &technology->enabled);
567 connman_dbus_dict_append_basic(&dict, "Connected",
569 &technology->connected);
571 connman_dbus_dict_append_basic(&dict, "Tethering",
573 &technology->tethering);
575 if (technology->tethering_ident != NULL)
576 connman_dbus_dict_append_basic(&dict, "TetheringIdentifier",
578 &technology->tethering_ident);
580 if (technology->tethering_passphrase != NULL)
581 connman_dbus_dict_append_basic(&dict, "TetheringPassphrase",
583 &technology->tethering_passphrase);
585 connman_dbus_dict_close(iter, &dict);
588 static void technology_added_signal(struct connman_technology *technology)
591 DBusMessageIter iter;
593 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
594 CONNMAN_MANAGER_INTERFACE, "TechnologyAdded");
598 dbus_message_iter_init_append(signal, &iter);
599 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
601 append_properties(&iter, technology);
603 dbus_connection_send(connection, signal, NULL);
604 dbus_message_unref(signal);
607 static void technology_removed_signal(struct connman_technology *technology)
609 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
610 CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
611 DBUS_TYPE_OBJECT_PATH, &technology->path,
615 static DBusMessage *get_properties(DBusConnection *conn,
616 DBusMessage *message, void *user_data)
618 struct connman_technology *technology = user_data;
620 DBusMessageIter iter;
622 reply = dbus_message_new_method_return(message);
626 dbus_message_iter_init_append(reply, &iter);
627 append_properties(&iter, technology);
632 void __connman_technology_list_struct(DBusMessageIter *array)
635 DBusMessageIter entry;
637 for (list = technology_list; list; list = list->next) {
638 struct connman_technology *technology = list->data;
640 if (technology->path == NULL ||
641 (technology->rfkill_driven == TRUE &&
642 technology->hardblocked == TRUE))
645 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
647 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
649 append_properties(&entry, technology);
650 dbus_message_iter_close_container(array, &entry);
654 static gboolean technology_pending_reply(gpointer user_data)
656 struct connman_technology *technology = user_data;
659 /* Power request timedout, send ETIMEDOUT. */
660 if (technology->pending_reply != NULL) {
661 reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
663 g_dbus_send_message(connection, reply);
665 dbus_message_unref(technology->pending_reply);
666 technology->pending_reply = NULL;
667 technology->pending_timeout = 0;
673 static int technology_affect_devices(struct connman_technology *technology,
674 connman_bool_t enable_device)
679 for (list = technology->device_list; list; list = list->next) {
680 struct connman_device *device = list->data;
682 if (enable_device == TRUE)
683 err = __connman_device_enable(device);
685 err = __connman_device_disable(device);
691 static int technology_enable(struct connman_technology *technology)
696 DBG("technology %p enable", technology);
698 __sync_synchronize();
699 if (technology->enabled == TRUE)
702 if (technology->pending_reply != NULL)
705 if (technology->rfkill_driven == TRUE)
706 err = __connman_rfkill_block(technology->type, FALSE);
708 err_dev = technology_affect_devices(technology, TRUE);
710 if (technology->rfkill_driven == FALSE)
716 static int technology_disable(struct connman_technology *technology)
720 DBG("technology %p disable", technology);
722 __sync_synchronize();
723 if (technology->enabled == FALSE)
726 if (technology->pending_reply != NULL)
729 if (technology->tethering == TRUE)
730 set_tethering(technology, FALSE);
732 err = technology_affect_devices(technology, FALSE);
734 if (technology->rfkill_driven == TRUE)
735 err = __connman_rfkill_block(technology->type, TRUE);
740 static DBusMessage *set_powered(struct connman_technology *technology,
741 DBusMessage *msg, connman_bool_t powered)
743 DBusMessage *reply = NULL;
746 if (technology->rfkill_driven && technology->hardblocked == TRUE) {
752 err = technology_enable(technology);
754 err = technology_disable(technology);
757 technology->enable_persistent = powered;
758 technology_save(technology);
762 if (err == -EINPROGRESS) {
763 technology->pending_reply = dbus_message_ref(msg);
764 technology->pending_timeout = g_timeout_add_seconds(10,
765 technology_pending_reply, technology);
766 } else if (err == -EALREADY) {
768 reply = __connman_error_already_enabled(msg);
770 reply = __connman_error_already_disabled(msg);
772 reply = __connman_error_failed(msg, -err);
774 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
779 static DBusMessage *set_property(DBusConnection *conn,
780 DBusMessage *msg, void *data)
782 struct connman_technology *technology = data;
783 DBusMessageIter iter, value;
787 DBG("conn %p", conn);
789 if (dbus_message_iter_init(msg, &iter) == FALSE)
790 return __connman_error_invalid_arguments(msg);
792 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
793 return __connman_error_invalid_arguments(msg);
795 dbus_message_iter_get_basic(&iter, &name);
796 dbus_message_iter_next(&iter);
798 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
799 return __connman_error_invalid_arguments(msg);
801 dbus_message_iter_recurse(&iter, &value);
803 type = dbus_message_iter_get_arg_type(&value);
805 DBG("property %s", name);
807 if (g_str_equal(name, "Tethering") == TRUE) {
809 connman_bool_t tethering;
811 if (type != DBUS_TYPE_BOOLEAN)
812 return __connman_error_invalid_arguments(msg);
814 if (connman_technology_is_tethering_allowed(technology->type)
816 DBG("%s tethering not allowed by config file",
817 __connman_service_type2string(technology->type));
818 return __connman_error_not_supported(msg);
821 dbus_message_iter_get_basic(&value, &tethering);
823 if (technology->tethering == tethering) {
824 if (tethering == FALSE)
825 return __connman_error_already_disabled(msg);
827 return __connman_error_already_enabled(msg);
830 err = set_tethering(technology, tethering);
832 return __connman_error_failed(msg, -err);
834 } else if (g_str_equal(name, "TetheringIdentifier") == TRUE) {
837 dbus_message_iter_get_basic(&value, &str);
839 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
840 return __connman_error_not_supported(msg);
842 if (strlen(str) < 1 || strlen(str) > 32)
843 return __connman_error_invalid_arguments(msg);
845 if (g_strcmp0(technology->tethering_ident, str) != 0) {
846 g_free(technology->tethering_ident);
847 technology->tethering_ident = g_strdup(str);
848 technology_save(technology);
850 connman_dbus_property_changed_basic(technology->path,
851 CONNMAN_TECHNOLOGY_INTERFACE,
852 "TetheringIdentifier",
854 &technology->tethering_ident);
856 } else if (g_str_equal(name, "TetheringPassphrase") == TRUE) {
859 dbus_message_iter_get_basic(&value, &str);
861 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
862 return __connman_error_not_supported(msg);
864 if (strlen(str) < 8 || strlen(str) > 63)
865 return __connman_error_passphrase_required(msg);
867 if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
868 g_free(technology->tethering_passphrase);
869 technology->tethering_passphrase = g_strdup(str);
870 technology_save(technology);
872 connman_dbus_property_changed_basic(technology->path,
873 CONNMAN_TECHNOLOGY_INTERFACE,
874 "TetheringPassphrase",
876 &technology->tethering_passphrase);
878 } else if (g_str_equal(name, "Powered") == TRUE) {
879 connman_bool_t enable;
881 if (type != DBUS_TYPE_BOOLEAN)
882 return __connman_error_invalid_arguments(msg);
884 dbus_message_iter_get_basic(&value, &enable);
886 return set_powered(technology, msg, enable);
888 return __connman_error_invalid_property(msg);
890 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
893 static void reply_scan_pending(struct connman_technology *technology, int err)
897 DBG("technology %p err %d", technology, err);
899 while (technology->scan_pending != NULL) {
900 DBusMessage *msg = technology->scan_pending->data;
902 DBG("reply to %s", dbus_message_get_sender(msg));
905 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
907 reply = __connman_error_failed(msg, -err);
908 g_dbus_send_message(connection, reply);
909 dbus_message_unref(msg);
911 technology->scan_pending =
912 g_slist_delete_link(technology->scan_pending,
913 technology->scan_pending);
917 void __connman_technology_scan_started(struct connman_device *device)
919 DBG("device %p", device);
922 void __connman_technology_scan_stopped(struct connman_device *device)
925 struct connman_technology *technology;
926 enum connman_service_type type;
929 type = __connman_device_get_service_type(device);
930 technology = technology_find(type);
932 DBG("technology %p device %p", technology, device);
934 if (technology == NULL)
937 for (list = technology->device_list; list != NULL; list = list->next) {
938 struct connman_device *other_device = list->data;
940 if (device == other_device)
943 if (__connman_device_get_service_type(other_device) != type)
946 if (connman_device_get_scanning(other_device) == TRUE)
951 reply_scan_pending(technology, 0);
954 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
955 int result, const char *alpha2)
957 connman_bool_t regdom_set = FALSE;
958 struct connman_technology *technology;
959 enum connman_service_type type;
960 GSList *tech_drivers;
962 type = __connman_device_get_service_type(device);
963 technology = technology_find(type);
965 if (technology == NULL)
970 for (tech_drivers = technology->driver_list;
971 tech_drivers != NULL;
972 tech_drivers = g_slist_next(tech_drivers)) {
973 struct connman_technology_driver *driver =
976 if (driver->set_regdom != NULL) {
977 driver->set_regdom(technology, alpha2);
983 if (regdom_set == FALSE)
987 connman_technology_regdom_notify(technology, alpha2);
990 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
992 struct connman_technology *technology = data;
995 DBG ("technology %p request from %s", technology,
996 dbus_message_get_sender(msg));
998 dbus_message_ref(msg);
999 technology->scan_pending =
1000 g_slist_prepend(technology->scan_pending, msg);
1002 err = __connman_device_request_scan(technology->type);
1004 reply_scan_pending(technology, err);
1009 static const GDBusMethodTable technology_methods[] = {
1010 { GDBUS_DEPRECATED_METHOD("GetProperties",
1011 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
1013 { GDBUS_ASYNC_METHOD("SetProperty",
1014 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1015 NULL, set_property) },
1016 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
1020 static const GDBusSignalTable technology_signals[] = {
1021 { GDBUS_SIGNAL("PropertyChanged",
1022 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
1026 static gboolean technology_dbus_register(struct connman_technology *technology)
1028 if (technology->dbus_registered == TRUE ||
1029 (technology->rfkill_driven == TRUE &&
1030 technology->hardblocked == TRUE))
1033 if (g_dbus_register_interface(connection, technology->path,
1034 CONNMAN_TECHNOLOGY_INTERFACE,
1035 technology_methods, technology_signals,
1036 NULL, technology, NULL) == FALSE) {
1037 connman_error("Failed to register %s", technology->path);
1041 technology_added_signal(technology);
1042 technology->dbus_registered = TRUE;
1047 static struct connman_technology *technology_get(enum connman_service_type type)
1049 GSList *tech_drivers = NULL;
1050 struct connman_technology_driver *driver;
1051 struct connman_technology *technology;
1055 DBG("type %d", type);
1057 str = __connman_service_type2string(type);
1061 technology = technology_find(type);
1062 if (technology != NULL) {
1063 __sync_fetch_and_add(&technology->refcount, 1);
1067 /* First check if we have a driver for this technology type */
1068 for (list = driver_list; list; list = list->next) {
1069 driver = list->data;
1071 if (driver->type == type) {
1072 DBG("technology %p driver %p", technology, driver);
1073 tech_drivers = g_slist_append(tech_drivers, driver);
1077 if (tech_drivers == NULL) {
1078 DBG("No matching drivers found for %s.",
1079 __connman_service_type2string(type));
1083 technology = g_try_new0(struct connman_technology, 1);
1084 if (technology == NULL)
1087 technology->refcount = 1;
1089 technology->rfkill_driven = FALSE;
1090 technology->softblocked = FALSE;
1091 technology->hardblocked = FALSE;
1093 technology->type = type;
1094 technology->path = g_strdup_printf("%s/technology/%s",
1097 technology->device_list = NULL;
1099 technology->pending_reply = NULL;
1101 technology_load(technology);
1103 if (technology_dbus_register(technology) == FALSE) {
1108 technology_list = g_slist_prepend(technology_list, technology);
1110 technology->driver_list = tech_drivers;
1112 for (list = tech_drivers; list != NULL; list = g_slist_next(list)) {
1113 driver = list->data;
1115 if (driver->probe != NULL && driver->probe(technology) < 0)
1116 DBG("Driver probe failed for technology %p",
1120 DBG("technology %p", technology);
1125 static void technology_dbus_unregister(struct connman_technology *technology)
1127 if (technology->dbus_registered == FALSE)
1130 technology_removed_signal(technology);
1131 g_dbus_unregister_interface(connection, technology->path,
1132 CONNMAN_TECHNOLOGY_INTERFACE);
1134 technology->dbus_registered = FALSE;
1137 static void technology_put(struct connman_technology *technology)
1139 DBG("technology %p", technology);
1141 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
1144 reply_scan_pending(technology, -EINTR);
1146 while (technology->driver_list != NULL) {
1147 struct connman_technology_driver *driver;
1149 driver = technology->driver_list->data;
1151 if (driver->remove != NULL)
1152 driver->remove(technology);
1154 technology->driver_list =
1155 g_slist_delete_link(technology->driver_list,
1156 technology->driver_list);
1159 technology_list = g_slist_remove(technology_list, technology);
1161 technology_dbus_unregister(technology);
1163 g_slist_free(technology->device_list);
1165 g_free(technology->path);
1166 g_free(technology->regdom);
1167 g_free(technology->tethering_ident);
1168 g_free(technology->tethering_passphrase);
1172 void __connman_technology_add_interface(enum connman_service_type type,
1173 int index, const char *name, const char *ident)
1175 struct connman_technology *technology;
1176 GSList *tech_drivers;
1177 struct connman_technology_driver *driver;
1180 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1181 case CONNMAN_SERVICE_TYPE_SYSTEM:
1183 case CONNMAN_SERVICE_TYPE_ETHERNET:
1184 case CONNMAN_SERVICE_TYPE_WIFI:
1185 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1186 case CONNMAN_SERVICE_TYPE_CELLULAR:
1187 case CONNMAN_SERVICE_TYPE_GPS:
1188 case CONNMAN_SERVICE_TYPE_VPN:
1189 case CONNMAN_SERVICE_TYPE_GADGET:
1193 connman_info("Adding interface %s [ %s ]", name,
1194 __connman_service_type2string(type));
1196 technology = technology_find(type);
1198 if (technology == NULL)
1201 for (tech_drivers = technology->driver_list; tech_drivers != NULL;
1202 tech_drivers = g_slist_next(tech_drivers)) {
1203 driver = tech_drivers->data;
1205 if(driver->add_interface != NULL)
1206 driver->add_interface(technology, index, name, ident);
1210 void __connman_technology_remove_interface(enum connman_service_type type,
1211 int index, const char *name, const char *ident)
1213 struct connman_technology *technology;
1214 GSList *tech_drivers;
1215 struct connman_technology_driver *driver;
1218 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1219 case CONNMAN_SERVICE_TYPE_SYSTEM:
1221 case CONNMAN_SERVICE_TYPE_ETHERNET:
1222 case CONNMAN_SERVICE_TYPE_WIFI:
1223 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1224 case CONNMAN_SERVICE_TYPE_CELLULAR:
1225 case CONNMAN_SERVICE_TYPE_GPS:
1226 case CONNMAN_SERVICE_TYPE_VPN:
1227 case CONNMAN_SERVICE_TYPE_GADGET:
1231 connman_info("Remove interface %s [ %s ]", name,
1232 __connman_service_type2string(type));
1234 technology = technology_find(type);
1236 if (technology == NULL)
1239 for (tech_drivers = technology->driver_list; tech_drivers != NULL;
1240 tech_drivers = g_slist_next(tech_drivers)) {
1241 driver = tech_drivers->data;
1243 if(driver->remove_interface != NULL)
1244 driver->remove_interface(technology, index);
1248 int __connman_technology_add_device(struct connman_device *device)
1250 struct connman_technology *technology;
1251 enum connman_service_type type;
1253 DBG("device %p", device);
1255 type = __connman_device_get_service_type(device);
1257 technology = technology_get(type);
1258 if (technology == NULL) {
1260 * Since no driver can be found for this device at the moment we
1261 * add it to the techless device list.
1263 techless_device_list = g_slist_prepend(techless_device_list,
1269 __sync_synchronize();
1270 if (technology->rfkill_driven == TRUE) {
1271 if (technology->enabled == TRUE)
1272 __connman_device_enable(device);
1274 __connman_device_disable(device);
1279 if (technology->enable_persistent == TRUE &&
1280 global_offlinemode == FALSE) {
1281 int err = __connman_device_enable(device);
1283 * connman_technology_add_device() calls __connman_device_enable()
1284 * but since the device is already enabled, the calls does not
1285 * propagate through to connman_technology_enabled via
1286 * connman_device_set_powered.
1288 if (err == -EALREADY)
1289 __connman_technology_enabled(type);
1291 /* if technology persistent state is offline */
1292 if (technology->enable_persistent == FALSE)
1293 __connman_device_disable(device);
1296 technology->device_list = g_slist_prepend(technology->device_list,
1302 int __connman_technology_remove_device(struct connman_device *device)
1304 struct connman_technology *technology;
1305 enum connman_service_type type;
1307 DBG("device %p", device);
1309 type = __connman_device_get_service_type(device);
1311 technology = technology_find(type);
1312 if (technology == NULL) {
1313 techless_device_list = g_slist_remove(techless_device_list,
1318 technology->device_list = g_slist_remove(technology->device_list,
1320 technology_put(technology);
1325 static void powered_changed(struct connman_technology *technology)
1327 if (technology->dbus_registered == FALSE)
1330 if (technology->pending_reply != NULL) {
1331 g_dbus_send_reply(connection,
1332 technology->pending_reply, DBUS_TYPE_INVALID);
1333 dbus_message_unref(technology->pending_reply);
1334 technology->pending_reply = NULL;
1336 g_source_remove(technology->pending_timeout);
1337 technology->pending_timeout = 0;
1340 __sync_synchronize();
1341 connman_dbus_property_changed_basic(technology->path,
1342 CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
1343 DBUS_TYPE_BOOLEAN, &technology->enabled);
1346 static int technology_enabled(struct connman_technology *technology)
1348 __sync_synchronize();
1349 if (technology->enabled == TRUE)
1352 technology->enabled = TRUE;
1354 powered_changed(technology);
1359 int __connman_technology_enabled(enum connman_service_type type)
1361 struct connman_technology *technology;
1363 technology = technology_find(type);
1364 if (technology == NULL)
1367 if (technology->rfkill_driven == TRUE)
1370 return technology_enabled(technology);
1373 static int technology_disabled(struct connman_technology *technology)
1375 __sync_synchronize();
1376 if (technology->enabled == FALSE)
1379 technology->enabled = FALSE;
1381 powered_changed(technology);
1386 int __connman_technology_disabled(enum connman_service_type type)
1388 struct connman_technology *technology;
1391 technology = technology_find(type);
1392 if (technology == NULL)
1395 if (technology->rfkill_driven == TRUE)
1398 for (list = technology->device_list; list != NULL; list = list->next) {
1399 struct connman_device *device = list->data;
1401 if (connman_device_get_powered(device) == TRUE)
1405 return technology_disabled(technology);
1408 int __connman_technology_set_offlinemode(connman_bool_t offlinemode)
1413 if (global_offlinemode == offlinemode)
1416 DBG("offlinemode %s", offlinemode ? "On" : "Off");
1419 * This is a bit tricky. When you set offlinemode, there is no
1420 * way to differentiate between attempting offline mode and
1421 * resuming offlinemode from last saved profile. We need that
1422 * information in rfkill_update, otherwise it falls back on the
1423 * technology's persistent state. Hence we set the offline mode here
1424 * but save it & call the notifier only if its successful.
1427 global_offlinemode = offlinemode;
1429 /* Traverse technology list, enable/disable each technology. */
1430 for (list = technology_list; list; list = list->next) {
1431 struct connman_technology *technology = list->data;
1434 err = technology_disable(technology);
1436 if (!offlinemode && technology->enable_persistent)
1437 err = technology_enable(technology);
1440 if (err == 0 || err == -EINPROGRESS || err == -EALREADY) {
1441 connman_technology_save_offlinemode();
1442 __connman_notifier_offlinemode(offlinemode);
1444 global_offlinemode = connman_technology_load_offlinemode();
1449 void __connman_technology_set_connected(enum connman_service_type type,
1450 connman_bool_t connected)
1452 struct connman_technology *technology;
1454 technology = technology_find(type);
1455 if (technology == NULL)
1458 DBG("technology %p connected %d", technology, connected);
1460 technology->connected = connected;
1462 connman_dbus_property_changed_basic(technology->path,
1463 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
1464 DBUS_TYPE_BOOLEAN, &connected);
1467 static connman_bool_t technology_apply_rfkill_change(struct connman_technology *technology,
1468 connman_bool_t softblock,
1469 connman_bool_t hardblock,
1470 connman_bool_t new_rfkill)
1472 gboolean hardblock_changed = FALSE;
1473 gboolean apply = TRUE;
1474 GList *start, *list;
1476 DBG("technology %p --> %d/%d vs %d/%d",
1477 technology, softblock, hardblock,
1478 technology->softblocked, technology->hardblocked);
1480 if (technology->hardblocked == hardblock)
1481 goto softblock_change;
1483 if (!(new_rfkill == TRUE && hardblock == FALSE)) {
1484 start = g_hash_table_get_values(rfkill_list);
1486 for (list = start; list != NULL; list = list->next) {
1487 struct connman_rfkill *rfkill = list->data;
1489 if (rfkill->type != technology->type)
1492 if (rfkill->hardblock != hardblock)
1500 goto softblock_change;
1502 technology->hardblocked = hardblock;
1503 hardblock_changed = TRUE;
1506 if (apply == FALSE && technology->softblocked != softblock)
1510 return technology->hardblocked;
1512 technology->softblocked = softblock;
1514 if (technology->hardblocked == TRUE ||
1515 technology->softblocked == TRUE) {
1516 if (technology_disabled(technology) != -EALREADY)
1517 technology_affect_devices(technology, FALSE);
1518 } else if (technology->hardblocked == FALSE &&
1519 technology->softblocked == FALSE) {
1520 if (technology_enabled(technology) != -EALREADY)
1521 technology_affect_devices(technology, TRUE);
1524 if (hardblock_changed == TRUE) {
1525 if (technology->hardblocked == TRUE) {
1526 DBG("%s is switched off.", get_name(technology->type));
1527 technology_dbus_unregister(technology);
1529 technology_dbus_register(technology);
1532 return technology->hardblocked;
1535 int __connman_technology_add_rfkill(unsigned int index,
1536 enum connman_service_type type,
1537 connman_bool_t softblock,
1538 connman_bool_t hardblock)
1540 struct connman_technology *technology;
1541 struct connman_rfkill *rfkill;
1543 DBG("index %u type %d soft %u hard %u", index, type,
1544 softblock, hardblock);
1546 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1550 rfkill = g_try_new0(struct connman_rfkill, 1);
1554 rfkill->index = index;
1555 rfkill->type = type;
1556 rfkill->softblock = softblock;
1557 rfkill->hardblock = hardblock;
1559 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
1562 technology = technology_get(type);
1563 /* If there is no driver for this type, ignore it. */
1564 if (technology == NULL)
1567 technology->rfkill_driven = TRUE;
1569 /* If hardblocked, there is no need to handle softblocked state */
1570 if (technology_apply_rfkill_change(technology,
1571 softblock, hardblock, TRUE) == TRUE)
1575 * Depending on softblocked state we unblock/block according to
1576 * offlinemode and persistente state.
1578 if (technology->softblocked == TRUE &&
1579 global_offlinemode == FALSE &&
1580 technology->enable_persistent == TRUE)
1581 return __connman_rfkill_block(type, FALSE);
1582 else if (technology->softblocked == FALSE &&
1583 (global_offlinemode == TRUE ||
1584 technology->enable_persistent == FALSE))
1585 return __connman_rfkill_block(type, TRUE);
1590 int __connman_technology_update_rfkill(unsigned int index,
1591 enum connman_service_type type,
1592 connman_bool_t softblock,
1593 connman_bool_t hardblock)
1595 struct connman_technology *technology;
1596 struct connman_rfkill *rfkill;
1598 DBG("index %u soft %u hard %u", index, softblock, hardblock);
1600 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1604 if (rfkill->softblock == softblock &&
1605 rfkill->hardblock == hardblock)
1608 rfkill->softblock = softblock;
1609 rfkill->hardblock = hardblock;
1611 technology = technology_find(type);
1612 /* If there is no driver for this type, ignore it. */
1613 if (technology == NULL)
1616 /* If hardblocked, there is no need to handle softblocked state */
1617 if (technology_apply_rfkill_change(technology,
1618 softblock, hardblock, FALSE) == TRUE)
1621 if (global_offlinemode == TRUE)
1625 * Depending on softblocked state we unblock/block according to
1628 if (technology->softblocked == TRUE &&
1629 technology->enable_persistent == TRUE)
1630 return __connman_rfkill_block(type, FALSE);
1631 else if (technology->softblocked == FALSE &&
1632 technology->enable_persistent == FALSE)
1633 return __connman_rfkill_block(type, TRUE);
1638 int __connman_technology_remove_rfkill(unsigned int index,
1639 enum connman_service_type type)
1641 struct connman_technology *technology;
1642 struct connman_rfkill *rfkill;
1644 DBG("index %u", index);
1646 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1650 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
1652 technology = technology_find(type);
1653 if (technology == NULL)
1656 technology_apply_rfkill_change(technology,
1657 technology->softblocked, !technology->hardblocked, FALSE);
1659 technology_put(technology);
1664 int __connman_technology_init(void)
1668 connection = connman_dbus_get_connection();
1670 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1673 global_offlinemode = connman_technology_load_offlinemode();
1675 /* This will create settings file if it is missing */
1676 connman_technology_save_offlinemode();
1681 void __connman_technology_cleanup(void)
1685 g_hash_table_destroy(rfkill_list);
1687 dbus_connection_unref(connection);