From b698719b876fdf627c57300bb14e52b20c8c0fe0 Mon Sep 17 00:00:00 2001 From: Jaehyun Kim Date: Mon, 20 Dec 2021 18:02:49 +0900 Subject: [PATCH] Add CAPIs to handle Wi-Fi roaming signal Change-Id: I0330789ad6b7be26776c42e1bf022862898a745c Signed-off-by: Jaehyun Kim --- include/wifi-manager-extension.h | 54 ++++++++++++++++++++ packaging/capi-network-wifi-manager.spec | 4 +- src/network_info.h | 2 + src/network_interface.h | 6 +++ src/network_internal.h | 1 + src/network_signal.c | 88 +++++++++++++++++++++++++++++++- src/wifi_internal.c | 38 ++++++++++++++ src/wifi_internal.h | 2 + src/wifi_manager.c | 41 +++++++++++++++ tools/manager-test/wman_test_main.c | 28 ++++++++++ 10 files changed, 261 insertions(+), 3 deletions(-) diff --git a/include/wifi-manager-extension.h b/include/wifi-manager-extension.h index 04ad726..0c7019f 100644 --- a/include/wifi-manager-extension.h +++ b/include/wifi-manager-extension.h @@ -68,6 +68,18 @@ typedef enum { } wifi_manager_mac_policy_e; /** + * @brief Enumeration for the Wi-Fi Roemaing State. + * @since_tizen 7.0 + */ +typedef enum { + WIFI_MANAGER_ROAM_UNKNOWN, /**< Unknown */ + WIFI_MANAGER_ROAM_SCAN_REQUIRED, /**< The SNR and signal of the connected AP are weakened */ + WIFI_MANAGER_ROAM_STARTED, /**< Wi-Fi Roaming is started */ + WIFI_MANAGER_ROAM_FAILURE, /**< Wi-Fi Roaming failed */ + WIFI_MANAGER_ROAM_SUCCESS, /**< Wi-Fi Roaming is successful. */ +} wifi_manager_roam_e; + +/** * @brief The Wi-Fi netlink scan handle. * @since_tizen 5.0 */ @@ -756,6 +768,48 @@ int wifi_manager_set_country_code(wifi_manager_h wifi, const char *country); int wifi_manager_get_country_code(wifi_manager_h wifi, char **country_code); /** + * @brief Called when the Roaming state is changed. + * @since_tizen 7.0 + * @param[in] state The Wi-Fi roaming state + * @param[in] cur_bssid The MAC address of connected AP + * @param[in] dst_bssid The MAC address of AP to roam + * @param[in] user_data The user data passed from the callback registration function + * @see wifi_manager_set_roaming_cb() + * @see wifi_manager_unset_roaming_cb() + */ +typedef void(*wifi_manager_roaming_state_changed_cb)(wifi_manager_roam_e state, + char *cur_bssid, char *dst_bssid, void *user_data); + +/** + * @brief Registers the callback called when the Roaming state is changed. + * @since_tizen 7.0 + * @param[in] wifi The Wi-Fi handle + * @param[in] callback The callback function to be called + * @param[in] user_data The user data passed to the callback function + * @return 0 on success, otherwise negative error value + * @retval #WIFI_MANAGER_ERROR_NONE Successful + * @retval #WIFI_MANAGER_ERROR_NOT_INITIALIZED Not initialized + * @retval #WIFI_MANAGER_ERROR_INVALID_OPERATION Invalid operation + * @retval #WIFI_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #WIFI_MANAGER_ERROR_NOT_SUPPORTED Not supported + */ +int wifi_manager_set_roaming_cb(wifi_manager_h wifi, + wifi_manager_roaming_state_changed_cb callback, void *user_data); + +/** + * @brief Unregisters the callback called when the Roaming state is changed. + * @since_tizen 7.0 + * @param[in] wifi The Wi-Fi handle + * @return 0 on success, otherwise negative error value + * @retval #WIFI_MANAGER_ERROR_NONE Successful + * @retval #WIFI_MANAGER_ERROR_NOT_INITIALIZED Not initialized + * @retval #WIFI_MANAGER_ERROR_INVALID_OPERATION Invalid operation + * @retval #WIFI_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #WIFI_MANAGER_ERROR_NOT_SUPPORTED Not supported + */ +int wifi_manager_unset_roaming_cb(wifi_manager_h wifi); + +/** * @brief Checks available security types of the AP. * @details An AP may support several types of security modes together. * You can check all supported security modes with this API. diff --git a/packaging/capi-network-wifi-manager.spec b/packaging/capi-network-wifi-manager.spec index 90390bd..111eeb7 100644 --- a/packaging/capi-network-wifi-manager.spec +++ b/packaging/capi-network-wifi-manager.spec @@ -1,7 +1,7 @@ Name: capi-network-wifi-manager Summary: Network Wi-Fi library in TIZEN C API -Version: 1.3.12 -Release: 6 +Version: 1.3.13 +Release: 0 Group: System/Network License: Apache-2.0 Source0: %{name}-%{version}.tar.gz diff --git a/src/network_info.h b/src/network_info.h index d469cb1..8098747 100644 --- a/src/network_info.h +++ b/src/network_info.h @@ -71,6 +71,7 @@ typedef enum { NET_EVENT_WIFI_DPP_FAILED, NET_EVENT_WIFI_DPP_REMOVED, NET_EVENT_WIFI_DPP_EVENT_IND, /* TODO: Make this in detail */ + NET_EVENT_WIFI_ROAM_STATE_IND, } net_event_e; typedef struct { @@ -139,6 +140,7 @@ typedef struct { guint subscribe_id_connman_error; guint subscribe_id_connman_scandone; guint subscribe_id_connman_scanstarted; + guint subscribe_id_connman_roaming; guint subscribe_id_netconfig_wifi; char interface_name[NET_WLAN_IF_NAME_LEN]; diff --git a/src/network_interface.h b/src/network_interface.h index 9ffc6ff..75e68b2 100644 --- a/src/network_interface.h +++ b/src/network_interface.h @@ -247,6 +247,12 @@ typedef struct { char own_uri[MAX_DPP_URI_LEN]; } net_dpp_event_info_s; +typedef struct { + char *state; + char *cur_bssid; + char *dst_bssid; +} net_roam_event_info_s; + int net_register_client_ext(network_info_s **network_info, const char *interface_name, net_event_cb event_cb, void *user_data); void net_deregister_client_ext(network_info_s *network_info); diff --git a/src/network_internal.h b/src/network_internal.h index 455d07e..dbf1702 100644 --- a/src/network_internal.h +++ b/src/network_internal.h @@ -86,6 +86,7 @@ extern "C" { #define SIGNAL_SERVICES_CHANGED "ServicesChanged" #define SIGNAL_SCAN_DONE "ScanDone" #define SIGNAL_SCAN_CHANGED "ScanChanged" +#define SIGNAL_ROAMING_STATE_CHANGED "RoamingStateChanged" #define CONNMAN_WIFI_TECHNOLOGY_PREFIX CONNMAN_PATH "/technology/wifi" diff --git a/src/network_signal.c b/src/network_signal.c index c45ebe0..d4f02ea 100644 --- a/src/network_signal.c +++ b/src/network_signal.c @@ -33,6 +33,7 @@ struct cs_tid_info { guint subscribe_id_connman_error; guint subscribe_id_connman_scandone; guint subscribe_id_connman_scanstarted; + guint subscribe_id_connman_roaming; guint subscribe_id_netconfig_wifi; }; @@ -1063,6 +1064,70 @@ out: return NET_ERR_NONE; } +static int __net_handle_roaming_changed(network_info_s *network_info, GVariant *param) +{ + __NETWORK_FUNC_ENTER__; + + GVariant *var; + GVariantIter *iter = NULL; + const gchar *sub_key = NULL; + const gchar *value = NULL; + net_event_info_s *event_data = NULL; + net_roam_event_info_s roam_info = { 0, 0, 0}; + gchar *interface_name = NULL; + + int ret = NET_ERR_NONE; + + g_variant_get(param, "(a{sv})", &iter); + while (g_variant_iter_loop(iter, "{sv}", &sub_key, &var)) { + if (g_strcmp0(sub_key, "Interface") == 0) { + value = g_variant_get_string(var, NULL); + interface_name = g_strdup(value); + } else if (g_strcmp0(sub_key, "State") == 0) { + value = g_variant_get_string(var, NULL); + roam_info.state = g_strdup(value); + } else if (g_strcmp0(sub_key, "ConnectedBSSID") == 0) { + value = g_variant_get_string(var, NULL); + roam_info.cur_bssid = g_strdup(value); + } else if (g_strcmp0(sub_key, "TargetBSSID") == 0) { + value = g_variant_get_string(var, NULL); + roam_info.dst_bssid = g_strdup(value); + } + } + + WIFI_LOG(WIFI_INFO, "Interface: %s State: %s, Connected BSSID: %s, Target BSSID: %s", + interface_name, roam_info.state, roam_info.cur_bssid, roam_info.dst_bssid); + + if (g_strcmp0(interface_name, network_info->interface_name) != 0) + goto done; + + event_data = g_try_malloc0(sizeof(net_event_info_s)); + if (event_data == NULL) { + ret = NET_ERR_OUT_OF_MEMORY; + goto done; + } + + event_data->Event = NET_EVENT_WIFI_ROAM_STATE_IND; + event_data->Error = NET_ERR_NONE; + event_data->Datalength = sizeof(net_roam_event_info_s); + event_data->Data = &roam_info; + + if (network_info->event_callback) + network_info->event_callback(event_data, network_info->user_data); + + g_free(event_data); + +done: + g_variant_iter_free(iter); + g_free(interface_name); + g_free(roam_info.state); + g_free(roam_info.cur_bssid); + g_free(roam_info.dst_bssid); + + __NETWORK_FUNC_EXIT__; + return ret; +} + static void __net_connman_service_signal_filter(GDBusConnection *conn, const gchar *name, const gchar *path, const gchar *interface, const gchar *sig, GVariant *param, gpointer user_data) @@ -1827,6 +1892,8 @@ static void __net_connman_manager_signal_filter(GDBusConnection *conn, __net_handle_scan_changed(network_info, param); else if (g_strcmp0(sig, SIGNAL_SCAN_DONE) == 0) __net_handle_scan_done(network_info, param); + else if (g_strcmp0(sig, SIGNAL_ROAMING_STATE_CHANGED) == 0) + __net_handle_roaming_changed(network_info, param); } static void __net_netconfig_signal_filter(GDBusConnection *conn, @@ -2042,6 +2109,7 @@ void _net_set_cs_tid(network_info_s *network_info, int tid) tid_info->subscribe_id_connman_error = network_info->subscribe_id_connman_error; tid_info->subscribe_id_connman_scandone = network_info->subscribe_id_connman_scandone; tid_info->subscribe_id_connman_scanstarted = network_info->subscribe_id_connman_scanstarted; + tid_info->subscribe_id_connman_roaming = network_info->subscribe_id_connman_roaming; tid_info->subscribe_id_netconfig_wifi = network_info->subscribe_id_netconfig_wifi; WIFI_LOG(WIFI_INFO, "tid %d, tid_info %p", tid, tid_info); @@ -2085,6 +2153,7 @@ void _net_unset_cs_tid(int tid) g_dbus_connection_signal_unsubscribe(connection, tid_info->subscribe_id_connman_error); g_dbus_connection_signal_unsubscribe(connection, tid_info->subscribe_id_connman_scandone); g_dbus_connection_signal_unsubscribe(connection, tid_info->subscribe_id_connman_scanstarted); + g_dbus_connection_signal_unsubscribe(connection, tid_info->subscribe_id_connman_roaming); g_dbus_connection_signal_unsubscribe(connection, tid_info->subscribe_id_netconfig_wifi); g_object_unref(connection); @@ -2158,6 +2227,19 @@ int _net_register_signal(network_info_s *network_info) network_info, NULL); + /* Create connman technology roaming connection */ + network_info->subscribe_id_connman_roaming = g_dbus_connection_signal_subscribe( + network_info->connection, + CONNMAN_SERVICE, + CONNMAN_MANAGER_INTERFACE, + SIGNAL_ROAMING_STATE_CHANGED, + CONNMAN_MANAGER_PATH, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + __net_connman_manager_signal_filter, + network_info, + NULL); + /* Create net-config service connection */ network_info->subscribe_id_netconfig_wifi = g_dbus_connection_signal_subscribe( network_info->connection, @@ -2176,14 +2258,16 @@ int _net_register_signal(network_info_s *network_info) network_info->subscribe_id_connman_error == 0 || network_info->subscribe_id_connman_scandone == 0 || network_info->subscribe_id_connman_scanstarted == 0 || + network_info->subscribe_id_connman_roaming == 0 || network_info->subscribe_id_netconfig_wifi == 0) { WIFI_LOG(WIFI_ERROR, "Failed register signals " "connman_state(%d), connman_error(%d), connman_scandone(%d), " - "connman_scanstarted(%d), netconfig_wifi(%d)", + "connman_scanstarted(%d), connman_roaming(%d), netconfig_wifi(%d)", network_info->subscribe_id_connman_state, network_info->subscribe_id_connman_error, network_info->subscribe_id_connman_scandone, network_info->subscribe_id_connman_scanstarted, + network_info->subscribe_id_connman_roaming, network_info->subscribe_id_netconfig_wifi); _net_deregister_signal(network_info); Error = NET_ERR_INVALID_OPERATION; @@ -2208,6 +2292,8 @@ void _net_deregister_signal(network_info_s *network_info) g_dbus_connection_signal_unsubscribe(network_info->connection, network_info->subscribe_id_connman_scanstarted); g_dbus_connection_signal_unsubscribe(network_info->connection, + network_info->subscribe_id_connman_roaming); + g_dbus_connection_signal_unsubscribe(network_info->connection, network_info->subscribe_id_netconfig_wifi); } diff --git a/src/wifi_internal.c b/src/wifi_internal.c index 1faf134..0fc278e 100644 --- a/src/wifi_internal.c +++ b/src/wifi_internal.c @@ -1227,6 +1227,41 @@ static void __dpp_removed_cb(wifi_manager_handle_s *wifi_handle, g_p_dpp_current = NULL; } + +static void __roaming_state_changed_cb(wifi_manager_handle_s *wifi_handle, + net_roam_event_info_s *roam_event_info) +{ + char *cur_bssid = NULL; + char *dst_bssid = NULL; + char *state = roam_event_info->state; + wifi_manager_roam_e roam_state = WIFI_MANAGER_ROAM_UNKNOWN; + + if (state) { + if (!strcmp(state, "required")) { + roam_state = WIFI_MANAGER_ROAM_SCAN_REQUIRED; + cur_bssid = roam_event_info->cur_bssid; + } else if (!strcmp(state, "started")) { + roam_state = WIFI_MANAGER_ROAM_STARTED; + cur_bssid = roam_event_info->cur_bssid; + dst_bssid = roam_event_info->dst_bssid; + } else if (!strcmp(state, "failure")) { + roam_state = WIFI_MANAGER_ROAM_FAILURE; + cur_bssid = roam_event_info->cur_bssid; + dst_bssid = roam_event_info->dst_bssid; + } else if (!strcmp(state, "success")) { + roam_state = WIFI_MANAGER_ROAM_SUCCESS; + cur_bssid = roam_event_info->cur_bssid; + dst_bssid = roam_event_info->dst_bssid; + } + } + + WIFI_LOG(WIFI_INFO, "Roaming state: %s, cur_bssid %s, dst_bssid %s", + state, cur_bssid, dst_bssid); + + if (wifi_handle->roaming_state_changed_cb) + wifi_handle->roaming_state_changed_cb(roam_state, + cur_bssid, dst_bssid, wifi_handle->roaming_state_changed_user_data); +} //LCOV_EXCL_STOP static void _wifi_evt_cb(net_event_info_s *event_cb, void *user_data) @@ -1492,6 +1527,9 @@ static void _wifi_evt_cb(net_event_info_s *event_cb, void *user_data) case NET_EVENT_WIFI_DPP_REMOVED: __dpp_removed_cb(wifi_handle, (net_dpp_event_info_s *)event_cb->Data); break; + case NET_EVENT_WIFI_ROAM_STATE_IND: + __roaming_state_changed_cb(wifi_handle, (net_roam_event_info_s *)event_cb->Data); + break; //LCOV_EXCL_STOP default: break; diff --git a/src/wifi_internal.h b/src/wifi_internal.h index fd658d2..4358e75 100644 --- a/src/wifi_internal.h +++ b/src/wifi_internal.h @@ -261,6 +261,8 @@ typedef struct { void *forget_ap_user_data; wifi_manager_dpp_event_cb dpp_event_cb; void *dpp_event_user_data; + wifi_manager_roaming_state_changed_cb roaming_state_changed_cb; + void *roaming_state_changed_user_data; network_info_s *network_info; char interface_name[NET_WLAN_IF_NAME_LEN]; diff --git a/src/wifi_manager.c b/src/wifi_manager.c index eef1126..e4e02f1 100644 --- a/src/wifi_manager.c +++ b/src/wifi_manager.c @@ -85,6 +85,13 @@ static void __wifi_set_module_state_changed_cb(wifi_manager_handle_s *wifi_handl wifi_handle->module_state_changed_user_data = user_data; } +static void __wifi_set_roaming_state_changed_cb(wifi_manager_handle_s *wifi_handle, + void *callback, void *user_data) +{ + wifi_handle->roaming_state_changed_cb = callback; + wifi_handle->roaming_state_changed_user_data = user_data; +} + //LCOV_EXCL_STOP EXPORT_API int wifi_manager_initialize(wifi_manager_h *wifi) @@ -2185,3 +2192,37 @@ EXPORT_API int wifi_manager_get_country_code(wifi_manager_h wifi, char **country __NETWORK_CAPI_FUNC_EXIT__; return rv; } + +EXPORT_API int wifi_manager_set_roaming_cb(wifi_manager_h wifi, + wifi_manager_roaming_state_changed_cb callback, void *user_data) +{ + __NETWORK_CAPI_FUNC_ENTER__; + + CHECK_FEATURE_SUPPORTED(WIFI_FEATURE); + + RET_ERR_IF_HANDLE_IS_NOT_VALID_OR_NOT_INITIALIZED(wifi, __NETWORK_CAPI_FUNC_EXIT__); + + if (callback == NULL) { + WIFI_LOG(WIFI_ERROR, "Invalid parameter"); //LCOV_EXCL_LINE + return WIFI_MANAGER_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE + } + + __wifi_set_roaming_state_changed_cb(wifi, callback, user_data); + + __NETWORK_CAPI_FUNC_EXIT__; + return WIFI_MANAGER_ERROR_NONE; +} + +EXPORT_API int wifi_manager_unset_roaming_cb(wifi_manager_h wifi) +{ + __NETWORK_CAPI_FUNC_ENTER__; + + CHECK_FEATURE_SUPPORTED(WIFI_FEATURE); + + RET_ERR_IF_HANDLE_IS_NOT_VALID_OR_NOT_INITIALIZED(wifi, __NETWORK_CAPI_FUNC_EXIT__); + + __wifi_set_roaming_state_changed_cb(wifi, NULL, NULL); + + __NETWORK_CAPI_FUNC_EXIT__; + return WIFI_MANAGER_ERROR_NONE; +} diff --git a/tools/manager-test/wman_test_main.c b/tools/manager-test/wman_test_main.c index 0d492a9..b41cf02 100644 --- a/tools/manager-test/wman_test_main.c +++ b/tools/manager-test/wman_test_main.c @@ -135,6 +135,33 @@ static void __test_tdls_state_callback(wifi_manager_tdls_state_e state, char *pe printf(", state : TDLS Disconnected, Peer Mac Address [%s]\n", peer_mac_add); } +static void __test_roaming_state_changed_callback(wifi_manager_roam_e state, + char *cur_bssid, char *dst_bssid, void *user_data) +{ + printf("[%s] Wi-Fi Roaming state changed callback", (char *)user_data); + + switch (state) { + case WIFI_MANAGER_ROAM_SCAN_REQUIRED: + printf(", state : Scan Required"); + break; + case WIFI_MANAGER_ROAM_STARTED: + printf(", state : Roaming Started"); + break; + case WIFI_MANAGER_ROAM_FAILURE: + printf(", state : Romaing Failure"); + break; + case WIFI_MANAGER_ROAM_SUCCESS: + printf(", state : Romaing Success"); + break; + case WIFI_MANAGER_ROAM_UNKNOWN: + /* fall through */ + default: + printf(", state : Unknown"); + } + + printf(", cur_bssid: %s, dst_bssid: %s\n", cur_bssid, dst_bssid); +} + int wman_test_init(void) { int rv = wifi_manager_initialize(&wifi); @@ -149,6 +176,7 @@ int wman_test_init(void) wifi_manager_tdls_set_state_changed_cb(wifi, __test_tdls_state_callback, "1"); wifi_manager_tdls_set_discovered_cb(wifi, __test_tdls_discover_callback, "1"); wifi_manager_set_module_state_changed_cb(wifi, __test_get_wifi_module_state_callback, "1"); + wifi_manager_set_roaming_cb(wifi, __test_roaming_state_changed_callback, "1"); } else { printf("[1] Wifi init failed [%s]\n", wman_test_strerror(rv)); -- 2.7.4