X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Ftechnology.c;h=8166d17c763172c14d493f66ac2039acbc340658;hb=35f61b1f8f53033a7333b56be18328d426dc24a1;hp=42446b0b961612c34879a19c688dc5ae826a195e;hpb=c63eb830386932317033acd092a56f9b82755f4c;p=platform%2Fupstream%2Fconnman.git diff --git a/src/technology.c b/src/technology.c index 42446b0..8166d17 100644 --- a/src/technology.c +++ b/src/technology.c @@ -55,7 +55,7 @@ struct connman_technology { enum connman_service_type type; char *path; GSList *device_list; - int enabled; + connman_bool_t enabled; char *regdom; connman_bool_t connected; @@ -72,6 +72,11 @@ struct connman_technology { guint pending_timeout; GSList *scan_pending; + + connman_bool_t rfkill_driven; + connman_bool_t softblocked; + connman_bool_t hardblocked; + connman_bool_t dbus_registered; }; static GSList *driver_list = NULL; @@ -218,6 +223,10 @@ static int set_tethering(struct connman_technology *technology, technology->driver->set_tethering == NULL) return -EOPNOTSUPP; + __sync_synchronize(); + if (technology->enabled == FALSE) + return -EACCES; + bridge = __connman_tethering_get_bridge(); if (bridge == NULL) return -EOPNOTSUPP; @@ -244,6 +253,21 @@ void connman_technology_regdom_notify(struct connman_technology *technology, technology->regdom = g_strdup(alpha2); } +static int set_regdom_by_device(struct connman_technology *technology, + const char *alpha2) +{ + GSList *list; + + for (list = technology->device_list; list; list = list->next) { + struct connman_device *device = list->data; + + if (connman_device_set_regdom(device, alpha2) != 0) + return -ENOTSUP; + } + + return 0; +} + int connman_technology_set_regdom(const char *alpha2) { GSList *list; @@ -251,11 +275,14 @@ int connman_technology_set_regdom(const char *alpha2) for (list = technology_list; list; list = list->next) { struct connman_technology *technology = list->data; - if (technology->driver == NULL) - continue; + if (set_regdom_by_device(technology, alpha2) != 0) { + if (technology->driver == NULL) + continue; - if (technology->driver->set_regdom) - technology->driver->set_regdom(technology, alpha2); + if (technology->driver->set_regdom != NULL) + technology->driver->set_regdom(technology, + alpha2); + } } return 0; @@ -281,8 +308,6 @@ static const char *get_name(enum connman_service_type type) return "Wired"; case CONNMAN_SERVICE_TYPE_WIFI: return "WiFi"; - case CONNMAN_SERVICE_TYPE_WIMAX: - return "WiMAX"; case CONNMAN_SERVICE_TYPE_BLUETOOTH: return "Bluetooth"; case CONNMAN_SERVICE_TYPE_CELLULAR: @@ -292,7 +317,7 @@ static const char *get_name(enum connman_service_type type) return NULL; } -static void save_state(struct connman_technology *technology) +static void technology_save(struct connman_technology *technology) { GKeyFile *keyfile; gchar *identifier; @@ -310,6 +335,16 @@ static void save_state(struct connman_technology *technology) g_key_file_set_boolean(keyfile, identifier, "Enable", technology->enable_persistent); + if (technology->tethering_ident != NULL) + g_key_file_set_string(keyfile, identifier, + "Tethering.Identifier", + technology->tethering_ident); + + if (technology->tethering_passphrase != NULL) + g_key_file_set_string(keyfile, identifier, + "Tethering.Passphrase", + technology->tethering_passphrase); + done: g_free(identifier); @@ -320,7 +355,7 @@ done: return; } -static void load_state(struct connman_technology *technology) +static void technology_load(struct connman_technology *technology) { GKeyFile *keyfile; gchar *identifier; @@ -353,9 +388,15 @@ static void load_state(struct connman_technology *technology) else technology->enable_persistent = FALSE; - save_state(technology); + technology_save(technology); g_clear_error(&error); } + + technology->tethering_ident = g_key_file_get_string(keyfile, + identifier, "Tethering.Identifier", NULL); + + technology->tethering_passphrase = g_key_file_get_string(keyfile, + identifier, "Tethering.Passphrase", NULL); done: g_free(identifier); @@ -415,7 +456,6 @@ static void append_properties(DBusMessageIter *iter, { DBusMessageIter dict; const char *str; - connman_bool_t powered; connman_dbus_dict_open(iter, &dict); @@ -430,12 +470,9 @@ static void append_properties(DBusMessageIter *iter, DBUS_TYPE_STRING, &str); __sync_synchronize(); - if (technology->enabled > 0) - powered = TRUE; - else - powered = FALSE; connman_dbus_dict_append_basic(&dict, "Powered", - DBUS_TYPE_BOOLEAN, &powered); + DBUS_TYPE_BOOLEAN, + &technology->enabled); connman_dbus_dict_append_basic(&dict, "Connected", DBUS_TYPE_BOOLEAN, @@ -447,13 +484,13 @@ static void append_properties(DBusMessageIter *iter, if (technology->tethering_ident != NULL) connman_dbus_dict_append_basic(&dict, "TetheringIdentifier", - DBUS_TYPE_STRING, - &technology->tethering_ident); + DBUS_TYPE_STRING, + &technology->tethering_ident); if (technology->tethering_passphrase != NULL) connman_dbus_dict_append_basic(&dict, "TetheringPassphrase", - DBUS_TYPE_STRING, - &technology->tethering_passphrase); + DBUS_TYPE_STRING, + &technology->tethering_passphrase); connman_dbus_dict_close(iter, &dict); } @@ -510,7 +547,9 @@ void __connman_technology_list_struct(DBusMessageIter *array) for (list = technology_list; list; list = list->next) { struct connman_technology *technology = list->data; - if (technology->path == NULL) + if (technology->path == NULL || + (technology->rfkill_driven == TRUE && + technology->hardblocked == TRUE)) continue; dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT, @@ -541,142 +580,98 @@ static gboolean technology_pending_reply(gpointer user_data) return FALSE; } -static int technology_enable(struct connman_technology *technology, - DBusMessage *msg) +static int technology_affect_devices(struct connman_technology *technology, + connman_bool_t enable_device) { GSList *list; int err = 0; - int ret = -ENODEV; - DBusMessage *reply; - DBG("technology %p enable", technology); - - __sync_synchronize(); - if (technology->enabled > 0) { - err = -EALREADY; - goto done; - } + for (list = technology->device_list; list; list = list->next) { + struct connman_device *device = list->data; - if (technology->pending_reply != NULL) { - err = -EBUSY; - goto done; + if (enable_device == TRUE) + err = __connman_device_enable(device); + else + err = __connman_device_disable(device); } - if (msg != NULL) { - /* - * This is a bit of a trick. When msg is not NULL it means - * thats technology_enable was invoked from the manager API. - * Hence we save the state here. - */ - technology->enable_persistent = TRUE; - save_state(technology); - } + return err; +} - __connman_rfkill_block(technology->type, FALSE); +static int technology_enable(struct connman_technology *technology) +{ + DBG("technology %p enable", technology); - /* - * An empty device list means that devices in the technology - * were rfkill blocked. The unblock above will enable the devs. - */ - if (technology->device_list == NULL) { - ret = 0; - goto done; - } + __sync_synchronize(); + if (technology->enabled == TRUE) + return -EALREADY; - for (list = technology->device_list; list; list = list->next) { - struct connman_device *device = list->data; + if (technology->pending_reply != NULL) + return -EBUSY; - err = __connman_device_enable(device); - /* - * err = 0 : Device was enabled right away. - * If atleast one device gets enabled, we consider - * the technology to be enabled. - */ - if (err == 0) - ret = 0; - } + if (technology->rfkill_driven == TRUE) + return __connman_rfkill_block(technology->type, FALSE); -done: - if (ret == 0) { - if (msg != NULL) - g_dbus_send_reply(connection, msg, DBUS_TYPE_INVALID); - return ret; - } - - if (msg != NULL) { - if (err == -EINPROGRESS) { - technology->pending_reply = dbus_message_ref(msg); - technology->pending_timeout = g_timeout_add_seconds(10, - technology_pending_reply, technology); - } else { - reply = __connman_error_failed(msg, -err); - if (reply != NULL) - g_dbus_send_message(connection, reply); - } - } - - return err; + return technology_affect_devices(technology, TRUE); } -static int technology_disable(struct connman_technology *technology, - DBusMessage *msg) +static int technology_disable(struct connman_technology *technology) { - GSList *list; - int err = 0; - int ret = -ENODEV; - DBusMessage *reply; - DBG("technology %p disable", technology); __sync_synchronize(); - if (technology->enabled == 0) { - err = -EALREADY; - goto done; - } + if (technology->enabled == FALSE) + return -EALREADY; - if (technology->pending_reply != NULL) { - err = -EBUSY; - goto done; - } + if (technology->pending_reply != NULL) + return -EBUSY; if (technology->tethering == TRUE) set_tethering(technology, FALSE); - if (msg != NULL) { - technology->enable_persistent = FALSE; - save_state(technology); - } + if (technology->rfkill_driven == TRUE) + return __connman_rfkill_block(technology->type, TRUE); - __connman_rfkill_block(technology->type, TRUE); + return technology_affect_devices(technology, FALSE); +} - for (list = technology->device_list; list; list = list->next) { - struct connman_device *device = list->data; +static DBusMessage *set_powered(struct connman_technology *technology, + DBusMessage *msg, connman_bool_t powered) +{ + DBusMessage *reply = NULL; + int err = 0; - err = __connman_device_disable(device); - if (err == 0) - ret = 0; + if (technology->rfkill_driven && technology->hardblocked == TRUE) { + err = -EACCES; + goto make_reply; } -done: - if (ret == 0) { - if (msg != NULL) - g_dbus_send_reply(connection, msg, DBUS_TYPE_INVALID); - return ret; + if (powered == TRUE) + err = technology_enable(technology); + else + err = technology_disable(technology); + + if (err != -EBUSY) { + technology->enable_persistent = powered; + technology_save(technology); } - if (msg != NULL) { - if (err == -EINPROGRESS) { - technology->pending_reply = dbus_message_ref(msg); - technology->pending_timeout = g_timeout_add_seconds(10, +make_reply: + if (err == -EINPROGRESS) { + technology->pending_reply = dbus_message_ref(msg); + technology->pending_timeout = g_timeout_add_seconds(10, technology_pending_reply, technology); - } else { - reply = __connman_error_failed(msg, -err); - if (reply != NULL) - g_dbus_send_message(connection, reply); - } - } + } else if (err == -EALREADY) { + if (powered == TRUE) + reply = __connman_error_already_enabled(msg); + else + reply = __connman_error_already_disabled(msg); + } else if (err < 0) + reply = __connman_error_failed(msg, -err); + else + reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID); - return err; + return reply; } static DBusMessage *set_property(DBusConnection *conn, @@ -716,8 +711,12 @@ static DBusMessage *set_property(DBusConnection *conn, dbus_message_iter_get_basic(&value, &tethering); - if (technology->tethering == tethering) - return __connman_error_in_progress(msg); + if (technology->tethering == tethering) { + if (tethering == FALSE) + return __connman_error_already_disabled(msg); + else + return __connman_error_already_enabled(msg); + } err = set_tethering(technology, tethering); if (err < 0) @@ -731,7 +730,20 @@ static DBusMessage *set_property(DBusConnection *conn, if (technology->type != CONNMAN_SERVICE_TYPE_WIFI) return __connman_error_not_supported(msg); - technology->tethering_ident = g_strdup(str); + if (strlen(str) < 1 || strlen(str) > 32) + return __connman_error_invalid_arguments(msg); + + if (g_strcmp0(technology->tethering_ident, str) != 0) { + g_free(technology->tethering_ident); + technology->tethering_ident = g_strdup(str); + technology_save(technology); + + connman_dbus_property_changed_basic(technology->path, + CONNMAN_TECHNOLOGY_INTERFACE, + "TetheringIdentifier", + DBUS_TYPE_STRING, + &technology->tethering_ident); + } } else if (g_str_equal(name, "TetheringPassphrase") == TRUE) { const char *str; @@ -740,10 +752,20 @@ static DBusMessage *set_property(DBusConnection *conn, if (technology->type != CONNMAN_SERVICE_TYPE_WIFI) return __connman_error_not_supported(msg); - if (strlen(str) < 8) - return __connman_error_invalid_arguments(msg); + if (strlen(str) < 8 || strlen(str) > 63) + return __connman_error_passphrase_required(msg); + + if (g_strcmp0(technology->tethering_passphrase, str) != 0) { + g_free(technology->tethering_passphrase); + technology->tethering_passphrase = g_strdup(str); + technology_save(technology); - technology->tethering_passphrase = g_strdup(str); + connman_dbus_property_changed_basic(technology->path, + CONNMAN_TECHNOLOGY_INTERFACE, + "TetheringPassphrase", + DBUS_TYPE_STRING, + &technology->tethering_passphrase); + } } else if (g_str_equal(name, "Powered") == TRUE) { connman_bool_t enable; @@ -751,11 +773,8 @@ static DBusMessage *set_property(DBusConnection *conn, return __connman_error_invalid_arguments(msg); dbus_message_iter_get_basic(&value, &enable); - if (enable == TRUE) - technology_enable(technology, msg); - else - technology_disable(technology, msg); + return set_powered(technology, msg, enable); } else return __connman_error_invalid_property(msg); @@ -831,7 +850,7 @@ void __connman_technology_scan_stopped(struct connman_device *device) if (__connman_device_get_service_type(other_device) != type) continue; - if (__connman_device_scanning(other_device)) + if (connman_device_get_scanning(other_device) == TRUE) count += 1; } @@ -839,6 +858,31 @@ void __connman_technology_scan_stopped(struct connman_device *device) reply_scan_pending(technology, 0); } +void __connman_technology_notify_regdom_by_device(struct connman_device *device, + int result, const char *alpha2) +{ + struct connman_technology *technology; + enum connman_service_type type; + + type = __connman_device_get_service_type(device); + technology = technology_find(type); + + if (technology == NULL) + return; + + if (result < 0) { + if (technology->driver != NULL && + technology->driver->set_regdom != NULL) { + technology->driver->set_regdom(technology, alpha2); + return; + } + + alpha2 = NULL; + } + + connman_technology_regdom_notify(technology, alpha2); +} + static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data) { struct connman_technology *technology = data; @@ -862,7 +906,7 @@ static const GDBusMethodTable technology_methods[] = { { GDBUS_DEPRECATED_METHOD("GetProperties", NULL, GDBUS_ARGS({ "properties", "a{sv}" }), get_properties) }, - { GDBUS_METHOD("SetProperty", + { GDBUS_ASYNC_METHOD("SetProperty", GDBUS_ARGS({ "name", "s" }, { "value", "v" }), NULL, set_property) }, { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) }, @@ -875,6 +919,27 @@ static const GDBusSignalTable technology_signals[] = { { }, }; +static gboolean technology_dbus_register(struct connman_technology *technology) +{ + if (technology->dbus_registered == TRUE || + (technology->rfkill_driven == TRUE && + technology->hardblocked == TRUE)) + return TRUE; + + if (g_dbus_register_interface(connection, technology->path, + CONNMAN_TECHNOLOGY_INTERFACE, + technology_methods, technology_signals, + NULL, technology, NULL) == FALSE) { + connman_error("Failed to register %s", technology->path); + return FALSE; + } + + technology_added_signal(technology); + technology->dbus_registered = TRUE; + + return TRUE; +} + static struct connman_technology *technology_get(enum connman_service_type type) { struct connman_technology *technology; @@ -917,6 +982,10 @@ static struct connman_technology *technology_get(enum connman_service_type type) technology->refcount = 1; + technology->rfkill_driven = FALSE; + technology->softblocked = FALSE; + technology->hardblocked = FALSE; + technology->type = type; technology->path = g_strdup_printf("%s/technology/%s", CONNMAN_PATH, str); @@ -925,20 +994,14 @@ static struct connman_technology *technology_get(enum connman_service_type type) technology->pending_reply = NULL; - load_state(technology); + technology_load(technology); - if (g_dbus_register_interface(connection, technology->path, - CONNMAN_TECHNOLOGY_INTERFACE, - technology_methods, technology_signals, - NULL, technology, NULL) == FALSE) { - connman_error("Failed to register %s", technology->path); + if (technology_dbus_register(technology) == FALSE) { g_free(technology); return NULL; } - technology_list = g_slist_append(technology_list, technology); - - technology_added_signal(technology); + technology_list = g_slist_prepend(technology_list, technology); technology->driver = driver; err = driver->probe(technology); @@ -950,6 +1013,18 @@ static struct connman_technology *technology_get(enum connman_service_type type) return technology; } +static void technology_dbus_unregister(struct connman_technology *technology) +{ + if (technology->dbus_registered == FALSE) + return; + + technology_removed_signal(technology); + g_dbus_unregister_interface(connection, technology->path, + CONNMAN_TECHNOLOGY_INTERFACE); + + technology->dbus_registered = FALSE; +} + static void technology_put(struct connman_technology *technology) { DBG("technology %p", technology); @@ -966,15 +1041,14 @@ static void technology_put(struct connman_technology *technology) technology_list = g_slist_remove(technology_list, technology); - technology_removed_signal(technology); - - g_dbus_unregister_interface(connection, technology->path, - CONNMAN_TECHNOLOGY_INTERFACE); + technology_dbus_unregister(technology); g_slist_free(technology->device_list); g_free(technology->path); g_free(technology->regdom); + g_free(technology->tethering_ident); + g_free(technology->tethering_passphrase); g_free(technology); } @@ -989,7 +1063,6 @@ void __connman_technology_add_interface(enum connman_service_type type, return; case CONNMAN_SERVICE_TYPE_ETHERNET: case CONNMAN_SERVICE_TYPE_WIFI: - case CONNMAN_SERVICE_TYPE_WIMAX: case CONNMAN_SERVICE_TYPE_BLUETOOTH: case CONNMAN_SERVICE_TYPE_CELLULAR: case CONNMAN_SERVICE_TYPE_GPS: @@ -1022,7 +1095,6 @@ void __connman_technology_remove_interface(enum connman_service_type type, return; case CONNMAN_SERVICE_TYPE_ETHERNET: case CONNMAN_SERVICE_TYPE_WIFI: - case CONNMAN_SERVICE_TYPE_WIMAX: case CONNMAN_SERVICE_TYPE_BLUETOOTH: case CONNMAN_SERVICE_TYPE_CELLULAR: case CONNMAN_SERVICE_TYPE_GPS: @@ -1064,7 +1136,18 @@ int __connman_technology_add_device(struct connman_device *device) return -ENXIO; } - if (technology->enable_persistent && !global_offlinemode) { + __sync_synchronize(); + if (technology->rfkill_driven == TRUE) { + if (technology->enabled == TRUE) + __connman_device_enable(device); + else + __connman_device_disable(device); + + goto done; + } + + if (technology->enable_persistent == TRUE && + global_offlinemode == FALSE) { int err = __connman_device_enable(device); /* * connman_technology_add_device() calls __connman_device_enable() @@ -1076,10 +1159,11 @@ int __connman_technology_add_device(struct connman_device *device) __connman_technology_enabled(type); } /* if technology persistent state is offline */ - if (!technology->enable_persistent) + if (technology->enable_persistent == FALSE) __connman_device_disable(device); - technology->device_list = g_slist_append(technology->device_list, +done: + technology->device_list = g_slist_prepend(technology->device_list, device); return 0; @@ -1101,9 +1185,6 @@ int __connman_technology_remove_device(struct connman_device *device) return -ENXIO; } - if (__connman_device_scanning(device)) - __connman_technology_scan_stopped(device); - technology->device_list = g_slist_remove(technology->device_list, device); technology_put(technology); @@ -1113,17 +1194,36 @@ int __connman_technology_remove_device(struct connman_device *device) static void powered_changed(struct connman_technology *technology) { - connman_bool_t powered; + if (technology->dbus_registered == FALSE) + return; - __sync_synchronize(); - if (technology->enabled >0) - powered = TRUE; - else - powered = FALSE; + if (technology->pending_reply != NULL) { + g_dbus_send_reply(connection, + technology->pending_reply, DBUS_TYPE_INVALID); + dbus_message_unref(technology->pending_reply); + technology->pending_reply = NULL; + + g_source_remove(technology->pending_timeout); + technology->pending_timeout = 0; + } + __sync_synchronize(); connman_dbus_property_changed_basic(technology->path, CONNMAN_TECHNOLOGY_INTERFACE, "Powered", - DBUS_TYPE_BOOLEAN, &powered); + DBUS_TYPE_BOOLEAN, &technology->enabled); +} + +static int technology_enabled(struct connman_technology *technology) +{ + __sync_synchronize(); + if (technology->enabled == TRUE) + return -EALREADY; + + technology->enabled = TRUE; + + powered_changed(technology); + + return 0; } int __connman_technology_enabled(enum connman_service_type type) @@ -1134,16 +1234,21 @@ int __connman_technology_enabled(enum connman_service_type type) if (technology == NULL) return -ENXIO; - if (__sync_fetch_and_add(&technology->enabled, 1) == 0) - powered_changed(technology); + if (technology->rfkill_driven == TRUE) + return 0; - if (technology->pending_reply != NULL) { - g_dbus_send_reply(connection, technology->pending_reply, DBUS_TYPE_INVALID); - dbus_message_unref(technology->pending_reply); - g_source_remove(technology->pending_timeout); - technology->pending_reply = NULL; - technology->pending_timeout = 0; - } + return technology_enabled(technology); +} + +static int technology_disabled(struct connman_technology *technology) +{ + __sync_synchronize(); + if (technology->enabled == FALSE) + return -EALREADY; + + technology->enabled = FALSE; + + powered_changed(technology); return 0; } @@ -1151,23 +1256,23 @@ int __connman_technology_enabled(enum connman_service_type type) int __connman_technology_disabled(enum connman_service_type type) { struct connman_technology *technology; + GSList *list; technology = technology_find(type); if (technology == NULL) return -ENXIO; - if (technology->pending_reply != NULL) { - g_dbus_send_reply(connection, technology->pending_reply, DBUS_TYPE_INVALID); - dbus_message_unref(technology->pending_reply); - g_source_remove(technology->pending_timeout); - technology->pending_reply = NULL; - technology->pending_timeout = 0; - } + if (technology->rfkill_driven == TRUE) + return 0; + + for (list = technology->device_list; list != NULL; list = list->next) { + struct connman_device *device = list->data; - if (__sync_fetch_and_sub(&technology->enabled, 1) == 1) - powered_changed(technology); + if (connman_device_get_powered(device) == TRUE) + return 0; + } - return 0; + return technology_disabled(technology); } int __connman_technology_set_offlinemode(connman_bool_t offlinemode) @@ -1196,10 +1301,10 @@ int __connman_technology_set_offlinemode(connman_bool_t offlinemode) struct connman_technology *technology = list->data; if (offlinemode) - err = technology_disable(technology, NULL); + err = technology_disable(technology); if (!offlinemode && technology->enable_persistent) - err = technology_enable(technology, NULL); + err = technology_enable(technology); } if (err == 0 || err == -EINPROGRESS || err == -EALREADY) { @@ -1229,6 +1334,74 @@ void __connman_technology_set_connected(enum connman_service_type type, DBUS_TYPE_BOOLEAN, &connected); } +static connman_bool_t technology_apply_rfkill_change(struct connman_technology *technology, + connman_bool_t softblock, + connman_bool_t hardblock, + connman_bool_t new_rfkill) +{ + gboolean hardblock_changed = FALSE; + gboolean apply = TRUE; + GList *start, *list; + + DBG("technology %p --> %d/%d vs %d/%d", + technology, softblock, hardblock, + technology->softblocked, technology->hardblocked); + + if (technology->hardblocked == hardblock) + goto softblock_change; + + if (!(new_rfkill == TRUE && hardblock == FALSE)) { + start = g_hash_table_get_values(rfkill_list); + + for (list = start; list != NULL; list = list->next) { + struct connman_rfkill *rfkill = list->data; + + if (rfkill->type != technology->type) + continue; + + if (rfkill->hardblock != hardblock) + apply = FALSE; + } + + g_list_free(start); + } + + if (apply == FALSE) + goto softblock_change; + + technology->hardblocked = hardblock; + hardblock_changed = TRUE; + +softblock_change: + if (apply == FALSE && technology->softblocked != softblock) + apply = TRUE; + + if (apply == FALSE) + return technology->hardblocked; + + technology->softblocked = softblock; + + if (technology->hardblocked == TRUE || + technology->softblocked == TRUE) { + if (technology_disabled(technology) != -EALREADY) + technology_affect_devices(technology, FALSE); + } else if (technology->hardblocked == FALSE && + technology->softblocked == FALSE) { + if (technology_enabled(technology) != -EALREADY) + technology_affect_devices(technology, TRUE); + } + + if (hardblock_changed == TRUE) { + if (technology->hardblocked == TRUE) { + DBG("%s is switched off.", get_name(technology->type)); + technology_dbus_unregister(technology); + } else + technology_dbus_register(technology); + } + + return technology->hardblocked; +} + int __connman_technology_add_rfkill(unsigned int index, enum connman_service_type type, connman_bool_t softblock, @@ -1240,7 +1413,7 @@ int __connman_technology_add_rfkill(unsigned int index, DBG("index %u type %d soft %u hard %u", index, type, softblock, hardblock); - rfkill = g_hash_table_lookup(rfkill_list, &index); + rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index)); if (rfkill != NULL) goto done; @@ -1253,7 +1426,7 @@ int __connman_technology_add_rfkill(unsigned int index, rfkill->softblock = softblock; rfkill->hardblock = hardblock; - g_hash_table_insert(rfkill_list, &rfkill->index, rfkill); + g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill); done: technology = technology_get(type); @@ -1261,25 +1434,25 @@ done: if (technology == NULL) return -ENXIO; - if (hardblock) { - DBG("%s is switched off.", get_name(type)); + technology->rfkill_driven = TRUE; + + /* If hardblocked, there is no need to handle softblocked state */ + if (technology_apply_rfkill_change(technology, + softblock, hardblock, TRUE) == TRUE) return 0; - } /* - * If Offline mode is on, we softblock the device if it isnt already. - * If Offline mode is off, we rely on the persistent state of tech. + * Depending on softblocked state we unblock/block according to + * offlinemode and persistente state. */ - if (global_offlinemode) { - if (!softblock) - return __connman_rfkill_block(type, TRUE); - } else { - if (technology->enable_persistent && softblock) - return __connman_rfkill_block(type, FALSE); - /* if technology persistent state is offline */ - if (!technology->enable_persistent && !softblock) - return __connman_rfkill_block(type, TRUE); - } + if (technology->softblocked == TRUE && + global_offlinemode == FALSE && + technology->enable_persistent == TRUE) + return __connman_rfkill_block(type, FALSE); + else if (technology->softblocked == FALSE && + (global_offlinemode == TRUE || + technology->enable_persistent == FALSE)) + return __connman_rfkill_block(type, TRUE); return 0; } @@ -1294,33 +1467,40 @@ int __connman_technology_update_rfkill(unsigned int index, DBG("index %u soft %u hard %u", index, softblock, hardblock); - rfkill = g_hash_table_lookup(rfkill_list, &index); + rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index)); if (rfkill == NULL) return -ENXIO; if (rfkill->softblock == softblock && - rfkill->hardblock == hardblock) + rfkill->hardblock == hardblock) return 0; rfkill->softblock = softblock; rfkill->hardblock = hardblock; - if (hardblock) { - DBG("%s is switched off.", get_name(type)); - return 0; - } - technology = technology_find(type); /* If there is no driver for this type, ignore it. */ if (technology == NULL) return -ENXIO; - if (!global_offlinemode) { - if (technology->enable_persistent && softblock) - return __connman_rfkill_block(type, FALSE); - if (!technology->enable_persistent && !softblock) - return __connman_rfkill_block(type, TRUE); - } + /* If hardblocked, there is no need to handle softblocked state */ + if (technology_apply_rfkill_change(technology, + softblock, hardblock, FALSE) == TRUE) + return 0; + + if (global_offlinemode == TRUE) + return 0; + + /* + * Depending on softblocked state we unblock/block according to + * persistent state. + */ + if (technology->softblocked == TRUE && + technology->enable_persistent == TRUE) + return __connman_rfkill_block(type, FALSE); + else if (technology->softblocked == FALSE && + technology->enable_persistent == FALSE) + return __connman_rfkill_block(type, TRUE); return 0; } @@ -1333,16 +1513,19 @@ int __connman_technology_remove_rfkill(unsigned int index, DBG("index %u", index); - rfkill = g_hash_table_lookup(rfkill_list, &index); + rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index)); if (rfkill == NULL) return -ENXIO; - g_hash_table_remove(rfkill_list, &index); + g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index)); technology = technology_find(type); if (technology == NULL) return -ENXIO; + technology_apply_rfkill_change(technology, + technology->softblocked, !technology->hardblocked, FALSE); + technology_put(technology); return 0; @@ -1354,7 +1537,7 @@ int __connman_technology_init(void) connection = connman_dbus_get_connection(); - rfkill_list = g_hash_table_new_full(g_int_hash, g_int_equal, + rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_rfkill); global_offlinemode = connman_technology_load_offlinemode();