From dca8fc235371c789b9d5d7432f762fcdacfe13f5 Mon Sep 17 00:00:00 2001 From: Niraj Kumar Goit Date: Fri, 17 Nov 2017 09:49:37 +0530 Subject: [PATCH] [wifi-manager] Added CAPI for Netlink scan. When tethering is enabled 'wlan' interface is available but wifi device is in deactivated state and so to search APs wifi_manager_netlink_scan() API is used. When wifi device is in activated state use wifi_manager_scan() API instead. Change-Id: I81a96ae7462e3d9d1276d7266f7c58e02e480e54 Signed-off-by: Niraj Kumar Goit --- include/network_dbus.h | 1 + include/network_interface.h | 10 +++ include/network_internal.h | 2 + include/wifi_internal.h | 6 ++ include/wifi_manager_extension.h | 56 ++++++++++++++++ src/network_dbus.c | 57 ++++++++++++++++ src/network_interface.c | 38 +++++++++++ src/network_signal.c | 106 +++++++++++++++++++++++++++++ src/wifi_internal.c | 139 +++++++++++++++++++++++++++++++++++++++ src/wifi_manager.c | 34 ++++++++++ test/wifi_manager_test.c | 92 ++++++++++++++++++++++++++ 11 files changed, 541 insertions(+) diff --git a/include/network_dbus.h b/include/network_dbus.h index 9f268ef..8795d27 100755 --- a/include/network_dbus.h +++ b/include/network_dbus.h @@ -107,6 +107,7 @@ int _net_dbus_load_wifi_driver(gboolean wifi_picker_test); int _net_dbus_remove_wifi_driver(void); int _net_dbus_specific_scan_request(const char *ssid); int _net_dbus_bssid_scan_request(void); +int _net_dbus_netlink_scan_request(void); int _net_dbus_get_passpoint(int *enabled); int _net_dbus_set_passpoint(int enable); int _net_dbus_multi_scan_request(GSList *multi_scan_list, int type); diff --git a/include/network_interface.h b/include/network_interface.h index 7821f93..7cf9165 100755 --- a/include/network_interface.h +++ b/include/network_interface.h @@ -65,6 +65,7 @@ typedef enum { NET_EVENT_WIFI_WPS_RSP, NET_EVENT_WIFI_SCANNING_IND, NET_EVENT_WIFI_BSSID_SCAN_IND, + NET_EVENT_WIFI_NETLINK_SCAN_IND, NET_EVENT_WIFI_IP_CONFLICT_IND, NET_EVENT_WIFI_TDLS_DISCOVERED_IND, NET_EVENT_WIFI_TDLS_CONNECTED_IND, @@ -205,6 +206,14 @@ typedef struct { } net_bssid_scan_bss_info_s; typedef struct { + char ssid[NET_WLAN_ESSID_LEN + 1]; + char bssid[NET_WLAN_BSSID_LEN + 1]; + char vsie[NET_WLAN_MAX_VSIE_LEN + 1]; + int freq; + int rssi; +} net_netlink_scan_bss_info_s; + +typedef struct { net_event_e Event; /** CM Asynchronous event */ char ProfileName[NET_PROFILE_NAME_LEN_MAX+1]; /** Profile Identifier corresponding to the event */ net_err_e Error; /** Event Status */ @@ -252,6 +261,7 @@ int net_init_profile_info(net_profile_info_s *ProfInfo); int net_specific_scan_wifi(const char *ssid); int net_get_wps_pin(char **wps_pin); int net_bssid_scan_wifi(int activated); +int net_netlink_scan_wifi(void); int net_wifi_get_passpoint(int *enable); int net_wifi_set_passpoint(int enable); int net_wifi_get_scan_state(int *scan_state); diff --git a/include/network_internal.h b/include/network_internal.h index 27adc8a..1547210 100755 --- a/include/network_internal.h +++ b/include/network_internal.h @@ -96,6 +96,7 @@ extern "C" { #define NETCONFIG_SIGNAL_POWEROFF_COMPLETED "PowerOffCompleted" #define NETCONFIG_SIGNAL_SPECIFIC_SCAN_DONE "SpecificScanCompleted" #define NETCONFIG_SIGNAL_BSSID_SCAN_DONE "BssidScanCompleted" +#define NETCONFIG_SIGNAL_NETLINK_SCAN_DONE "NetlinkScanCompleted" #define NETCONFIG_SIGNAL_TDLS_PEER_FOUND "TDLSPeerFound" #define NETCONFIG_SIGNAL_TDLS_CONNECTED "TDLSConnect" #define NETCONFIG_SIGNAL_TDLS_DISCONNECTED "TDLSDisconnect" @@ -119,6 +120,7 @@ typedef enum { NETWORK_REQUEST_TYPE_ENROLL_WPS, NETWORK_REQUEST_TYPE_SPECIFIC_SCAN, NETWORK_REQUEST_TYPE_BSSID_SCAN, + NETWORK_REQUEST_TYPE_NETLINK_SCAN, NETWORK_REQUEST_TYPE_IP_CONFLICT, NETWORK_REQUEST_TYPE_MULTI_SCAN, NETWORK_REQUEST_TYPE_SET_DEFAULT, diff --git a/include/wifi_internal.h b/include/wifi_internal.h index d0b7f6e..a8766eb 100755 --- a/include/wifi_internal.h +++ b/include/wifi_internal.h @@ -93,6 +93,7 @@ typedef enum { WIFI_SCAN_CHANGED_CB, WIFI_SPECIFIC_SCAN_CB, WIFI_BSSID_SCAN_CB, + WIFI_NETLINK_SCAN_CB, WIFI_IP_CONFLICT_CB, WIFI_MULTI_SCAN_CB, WIFI_MANAGER_CONNECTION_STATE_CB, @@ -180,6 +181,8 @@ typedef struct { void *module_state_changed_user_data; wifi_manager_scan_finished_cb multi_scan_cb; void *multi_scan_user_data; + wifi_manager_netlink_scan_finished_cb netlink_scan_cb; + void *netlink_scan_user_data; } wifi_manager_handle_s; @@ -224,6 +227,7 @@ int _wifi_get_connected_profile(wifi_manager_ap_h *ap); int _wifi_foreach_found_ap(wifi_manager_found_ap_cb callback, void *user_data); int _wifi_foreach_found_specific_ap(wifi_manager_found_ap_cb callback, void *user_data); int _wifi_foreach_found_bssid_ap(wifi_manager_found_ap_cb callback, void *user_data); +int _wifi_foreach_found_netlink_scan_ap(wifi_manager_found_ap_cb callback, void *user_data); int _wifi_open_profile(wifi_manager_h wifi, wifi_manager_ap_h ap_h, wifi_manager_connected_cb callback, void *user_data); @@ -246,6 +250,8 @@ int _wifi_connect_with_wps_pin_without_ssid(wifi_manager_h wifi, int _wifi_cancel_wps(void); int _wifi_bssid_scan_request(wifi_manager_h wifi, wifi_manager_bssid_scan_finished_cb callback, void *user_data); +int _wifi_netlink_scan_request(wifi_manager_h wifi, + wifi_manager_netlink_scan_finished_cb callback, void *user_data); bool _wifi_check_multi_scan_validity(wifi_manager_specific_scan_h specific_scan); void _wifi_add_to_multi_scan_list(wifi_manager_specific_scan_h *specific_scan); diff --git a/include/wifi_manager_extension.h b/include/wifi_manager_extension.h index ea79196..79390df 100755 --- a/include/wifi_manager_extension.h +++ b/include/wifi_manager_extension.h @@ -234,6 +234,62 @@ int wifi_manager_set_ip_conflict_period(wifi_manager_h wifi, unsigned int initia int wifi_manager_get_ip_conflict_period(wifi_manager_h wifi, unsigned int *initial_time); /** + * @brief Called when the Netlink scan is finished. + * @since_tizen 5.0 + * @param[in] error_code The error code + * @param[in] user_data The user data passed from the callback registration function + * @see wifi_manager_netlink_scan() + */ +typedef void(*wifi_manager_netlink_scan_finished_cb)(wifi_manager_error_e error_code, void *user_data); + +/** + * @brief Gets the result of the netlink scan (i.e.BSSID, ESSID, Frequency, RSSI, VSIE). + * @details If tethering is enabled in device then wlan interface is available but + * wifi module is in deactivated state and wpa-supplicant service is not active. So + * in this case to search available APs wifi_manager_netlink_scan() API will be used. + * @since_tizen 5.0 + * @privlevel public + * @privilege %http://tizen.org/privilege/network.get + * @param[in] wifi The Wi-Fi handle + * @param[in] callback The callback 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_INVALID_PARAMETER Invalid parameter + * @retval #WIFI_MANAGER_ERROR_OPERATION_FAILED Operation failed + * @retval #WIFI_MANAGER_ERROR_NOT_SUPPORTED Not supported + * @post This function invokes wifi_manager_found_ap_cb(). + * @see wifi_manager_netlink_scan() + */ +int wifi_manager_foreach_found_netlink_scan_ap(wifi_manager_h wifi, + wifi_manager_found_ap_cb callback, void *user_data); + +/** + * @brief Starts netlink scan asynchronously. + * @details If tethering is enabled in device then wlan interface is available but + * wifi module is in deactivated state and wpa-supplicant service is not active. So + * in this case to search available APs use wifi_manager_netlink_scan() API. + * @since_tizen 5.0 + * @privlevel public + * @privilege %http://tizen.org/privilege/network.set \n + * %http://tizen.org/privilege/network.get + * @remarks This function needs both privileges. + * @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_INVALID_PARAMETER Invalid parameter + * @retval #WIFI_MANAGER_ERROR_INVALID_OPERATION Invalid operation + * @retval #WIFI_MANAGER_ERROR_OPERATION_FAILED Operation failed + * @retval #WIFI_MANAGER_ERROR_PERMISSION_DENIED Permission Denied + * @retval #WIFI_MANAGER_ERROR_NOT_SUPPORTED Not supported + * @post This function invokes wifi_manager_netlink_scan_finished_cb(). + */ +int wifi_manager_netlink_scan(wifi_manager_h wifi, + wifi_manager_netlink_scan_finished_cb callback, void *user_data); + +/** * @} */ diff --git a/src/network_dbus.c b/src/network_dbus.c index 861c0a4..ff1bc3a 100755 --- a/src/network_dbus.c +++ b/src/network_dbus.c @@ -563,6 +563,49 @@ static void __net_bssid_scan_wifi_reply(GObject *source_object, GAsyncResult *re __NETWORK_FUNC_EXIT__; } +static void __net_netlink_scan_wifi_reply(GObject *source_object, GAsyncResult *res, gpointer user_data) +{ + __NETWORK_FUNC_ENTER__; + + GDBusConnection *conn = NULL; + GError *error = NULL; + net_err_e Error = NET_ERR_NONE; + net_event_info_s event_data = { 0, }; + + conn = G_DBUS_CONNECTION(source_object); + g_dbus_connection_call_finish(conn, res, &error); + if (error != NULL) { + Error = __net_netconfig_error_string_to_enum(error->message); + g_error_free(error); + } + + if (Error != NET_ERR_NONE) { + WIFI_LOG(WIFI_ERROR, "netlink scan failed[%d]", Error); + + if (request_table[NETWORK_REQUEST_TYPE_NETLINK_SCAN].flag == TRUE) { + memset(&request_table[NETWORK_REQUEST_TYPE_NETLINK_SCAN], + 0, sizeof(network_request_table_s)); + + event_data.Event = NET_EVENT_WIFI_NETLINK_SCAN_IND; + event_data.Datalength = 0; + event_data.Data = NULL; + event_data.Error = Error; + + _net_dbus_pending_call_unref(); + + _net_client_callback(&event_data); + + __NETWORK_FUNC_EXIT__; + return; + } + } else + WIFI_LOG(WIFI_INFO, "netlink scan succeed"); + + _net_dbus_pending_call_unref(); + + __NETWORK_FUNC_EXIT__; +} + static void __net_set_passpoint_reply(GObject *source_object, GAsyncResult *res, gpointer user_data) { __NETWORK_FUNC_ENTER__; @@ -1938,6 +1981,20 @@ int _net_dbus_bssid_scan_request(void) return Error; } +int _net_dbus_netlink_scan_request(void) +{ + __NETWORK_FUNC_ENTER__; + net_err_e Error = NET_ERR_NONE; + + Error = _net_invoke_dbus_method_nonblock(NETCONFIG_SERVICE, + NETCONFIG_WIFI_PATH, NETCONFIG_WIFI_INTERFACE, + "NetlinkScan", NULL, 6 * DBUS_REPLY_TIMEOUT, + __net_netlink_scan_wifi_reply); + + __NETWORK_FUNC_EXIT__; + return Error; +} + int _net_dbus_get_passpoint(int *enabled) { __NETWORK_FUNC_ENTER__; diff --git a/src/network_interface.c b/src/network_interface.c index cee2c65..9e57fb2 100755 --- a/src/network_interface.c +++ b/src/network_interface.c @@ -1550,6 +1550,44 @@ int net_bssid_scan_wifi(int activated) return Error; } +int net_netlink_scan_wifi(void) +{ + __NETWORK_FUNC_ENTER__; + + net_err_e Error = NET_ERR_NONE; + + if (NetworkInfo.ref_count < 1) { + WIFI_LOG(WIFI_ERROR, "Application is not registered"); + __NETWORK_FUNC_EXIT__; + return NET_ERR_APP_NOT_REGISTERED; + } + + if (_net_dbus_is_pending_call_used() == TRUE) { + if (request_table[NETWORK_REQUEST_TYPE_NETLINK_SCAN].flag == TRUE) + return NET_ERR_IN_PROGRESS; + + WIFI_LOG(WIFI_ERROR, "pending call in progress"); + __NETWORK_FUNC_EXIT__; + return NET_ERR_INVALID_OPERATION; + } + + request_table[NETWORK_REQUEST_TYPE_NETLINK_SCAN].flag = TRUE; + + Error = _net_dbus_netlink_scan_request(); + + if (Error != NET_ERR_NONE) { + WIFI_LOG(WIFI_ERROR, + "_net_dbus_netlink_scan_request() failed. Error [%s]", + _net_print_error(Error)); + + memset(&request_table[NETWORK_REQUEST_TYPE_NETLINK_SCAN], 0, + sizeof(network_request_table_s)); + } + + __NETWORK_FUNC_EXIT__; + return Error; +} + int net_multi_scan_wifi(GSList *multi_scan_list, int type) { __NETWORK_FUNC_ENTER__; diff --git a/src/network_signal.c b/src/network_signal.c index 4478c5c..5496f2f 100755 --- a/src/network_signal.c +++ b/src/network_signal.c @@ -375,6 +375,110 @@ static int __net_handle_wifi_bssid_scan_rsp(GVariant *param) return NET_ERR_NONE; } +static int __net_handle_netlink_scan_resp(GSList *bss_info_list) +{ + __NETWORK_FUNC_ENTER__; + + int count = 0;; + net_event_info_s event_data = { 0, }; + + if (request_table[NETWORK_REQUEST_TYPE_NETLINK_SCAN].flag == TRUE) { + memset(&request_table[NETWORK_REQUEST_TYPE_NETLINK_SCAN], + 0, sizeof(network_request_table_s)); + + _net_dbus_pending_call_unref(); + + count = (int)g_slist_length(bss_info_list); + WIFI_LOG(WIFI_INFO, + "Received the signal: %s with total bss count = %d", + NETCONFIG_SIGNAL_NETLINK_SCAN_DONE, + count); + + event_data.Event = NET_EVENT_WIFI_NETLINK_SCAN_IND; + event_data.Datalength = count; + event_data.Data = bss_info_list; + + _net_client_callback(&event_data); + } else + g_slist_free_full(bss_info_list, g_free); + + __NETWORK_FUNC_EXIT__; + return NET_ERR_NONE; +} + +static int __net_handle_wifi_netlink_scan_rsp(GVariant *param) +{ + GVariantIter *iter = NULL; + GVariant *value = NULL; + gchar *key = NULL; + GSList *bss_info_list = NULL; + const gchar *ssid = NULL; + const gchar *bssid = NULL; + const gchar *vsie = NULL; + int freq = 0; + int rssi = 0; + gboolean ssid_found = FALSE; + gboolean bssid_found = FALSE; + gboolean freq_found = FALSE; + gboolean rssi_found = FALSE; + gboolean vsie_found = FALSE; + + g_variant_get(param, "(a{sv})", &iter); + + while (g_variant_iter_loop(iter, "{sv}", &key, &value)) { + if (g_strcmp0(key, "ssid") == 0) { + ssid = g_variant_get_string(value, NULL); + ssid_found = TRUE; + } else if (g_strcmp0(key, "bssid") == 0) { + bssid = g_variant_get_string(value, NULL); + bssid_found = TRUE; + } else if (g_strcmp0(key, "freq") == 0) { + freq = g_variant_get_int32(value); + freq_found = TRUE; + } else if (g_strcmp0(key, "rssi") == 0) { + rssi = g_variant_get_int32(value); + rssi_found = TRUE; + } else if (g_strcmp0(key, "vsie") == 0) { + vsie = g_variant_get_string(value, NULL); + vsie_found = TRUE; + } + + if (ssid_found == TRUE && bssid_found == TRUE && + freq_found == TRUE && rssi_found == TRUE && vsie_found == TRUE) { + net_netlink_scan_bss_info_s *bss = NULL; + bss = g_try_new0(net_netlink_scan_bss_info_s, 1); + if (bss == NULL) { + WIFI_LOG(WIFI_ERROR, "Memory allocation error"); + + g_slist_free_full(bss_info_list, g_free); + g_variant_unref(value); + g_free(key); + g_variant_iter_free(iter); + return NET_ERR_UNKNOWN; + } + + g_strlcpy(bss->ssid, ssid, strlen(ssid)+1); + g_strlcpy(bss->bssid, bssid, NET_WLAN_BSSID_LEN+1); + bss->freq = freq; + bss->rssi = rssi; + + WIFI_LOG(WIFI_INFO, "BSSID: %s, Freq: %d, rssi: %d, SSID: %s", bssid, freq, rssi, ssid); + if (strncmp(vsie, "dd", 2) == 0) { + WIFI_LOG(WIFI_INFO, "vsie: %s", vsie); + g_strlcpy(bss->vsie, vsie, strlen(vsie)+1); + } + + bss_info_list = g_slist_append(bss_info_list, bss); + + ssid_found = bssid_found = freq_found = rssi_found = vsie_found = FALSE; + } + } + g_variant_iter_free(iter); + __net_handle_netlink_scan_resp(bss_info_list); + + return NET_ERR_NONE; +} + static void __net_handle_state_ind(const char *profile_name, net_state_type_e profile_state) { @@ -1204,6 +1308,8 @@ static void __net_netconfig_signal_filter(GDBusConnection *conn, __net_handle_wifi_specific_scan_rsp(param); else if (g_strcmp0(sig, NETCONFIG_SIGNAL_BSSID_SCAN_DONE) == 0) __net_handle_wifi_bssid_scan_rsp(param); + else if (g_strcmp0(sig, NETCONFIG_SIGNAL_NETLINK_SCAN_DONE) == 0) + __net_handle_wifi_netlink_scan_rsp(param); else if (g_strcmp0(sig, NETCONFIG_SIGNAL_TDLS_PEER_FOUND) == 0) __net_handle_wifi_tdls_discover_event(param); else if (g_strcmp0(sig, NETCONFIG_SIGNAL_TDLS_CONNECTED) == 0) diff --git a/src/wifi_internal.c b/src/wifi_internal.c index a7da0e4..ba35ee4 100755 --- a/src/wifi_internal.c +++ b/src/wifi_internal.c @@ -369,6 +369,44 @@ static void __update_bss_profile_iterator(GSList *bss_list) } } +static void __update_netlink_scan_profile_iterator(GSList *bss_list) +{ + int count = 0; + GSList *list = bss_list; + + count = (int)g_slist_length(list); + if (count == 0) { + WIFI_LOG(WIFI_INFO, "No AP found !!"); + return; + } + + for (list = bss_list; list; list = list->next) { + + net_netlink_scan_bss_info_s *ap = (net_netlink_scan_bss_info_s *)list->data; + net_profile_info_s *profile = g_try_malloc0(sizeof(net_profile_info_s)); + if (profile == NULL) { + WIFI_LOG(WIFI_ERROR, "Failed to alloc profile"); + return; + } + + if (net_init_profile_info(profile) != NET_ERR_NONE) { + WIFI_LOG(WIFI_ERROR, "Failed to init profile"); + g_free(profile); + return; + } + + g_strlcpy(profile->essid, ap->ssid, NET_WLAN_ESSID_LEN+1); + g_strlcpy(profile->bssid, ap->bssid, NET_MAX_MAC_ADDR_LEN+1); + g_strlcpy(profile->vsie, ap->vsie, NET_WLAN_MAX_VSIE_LEN+1); + profile->vsie_len = strlen(ap->vsie); + profile->frequency = (unsigned int)ap->freq; + profile->Strength = 120 + ap->rssi; + + bss_profile_iterator = g_slist_append(bss_profile_iterator, + (net_profile_info_s *)profile); + } +} + static void __convert_profile_info_to_wifi_info(net_wifi_connection_info_s *wifi_info, net_profile_info_s *ap_info) { @@ -603,6 +641,17 @@ static void __set_bssid_scan_cb(wifi_manager_h wifi, } } +static void __set_netlink_scan_cb(wifi_manager_h wifi, + wifi_manager_netlink_scan_finished_cb user_cb, void *user_data) +{ + wifi_manager_handle_s *local_handle = (wifi_manager_handle_s *)wifi; + + if (user_cb) { + local_handle->netlink_scan_cb = user_cb; + local_handle->netlink_scan_user_data = user_data; + } +} + static void __set_multi_scan_cb(wifi_manager_h wifi, wifi_manager_scan_finished_cb user_cb, void *user_data) { @@ -774,6 +823,35 @@ static void __ip_conflict_cb(net_event_info_s *event_cb) } } +static void __netlink_scan_cb(net_event_info_s *event_cb) +{ + GSList *list; + wifi_manager_error_e error_code = WIFI_MANAGER_ERROR_NONE; + + __clear_profile_list(&bss_profile_iterator); + + if (event_cb->Error != NET_ERR_NONE) { + WIFI_LOG(WIFI_ERROR, "NETLINK scan failed!, Error [%d]\n", + event_cb->Error); + error_code = WIFI_MANAGER_ERROR_OPERATION_FAILED; + } else if (event_cb->Data) { + __update_netlink_scan_profile_iterator((GSList *)event_cb->Data); + WIFI_LOG(WIFI_INFO, "BSS AP count : %d\n", + (int)g_slist_length(bss_profile_iterator)); + } + + if (_wifi_get_callback_count_from_handle_list(WIFI_NETLINK_SCAN_CB)) { + for (list = wifi_manager_handle_list; list; list = list->next) { + wifi_manager_handle_s *local_handle = (wifi_manager_handle_s *)list->data; + if (local_handle->netlink_scan_cb) + local_handle->netlink_scan_cb(error_code, local_handle->netlink_scan_user_data); + + local_handle->netlink_scan_cb = NULL; + local_handle->netlink_scan_user_data = NULL; + } + } +} + static void __multi_scan_cb(net_event_info_s *event_cb) { GSList *list; @@ -1092,6 +1170,10 @@ static void _wifi_evt_cb(net_event_info_s *event_cb, void *user_data) WIFI_LOG(WIFI_INFO, "Got ip conflict event IND\n"); __ip_conflict_cb(event_cb); break; + case NET_EVENT_WIFI_NETLINK_SCAN_IND: + WIFI_LOG(WIFI_INFO, "Got NETLINK scan done IND\n"); + __netlink_scan_cb(event_cb); + break; case NET_EVENT_WIFI_SCAN_CHANGED: WIFI_LOG(WIFI_INFO, "Got Wi-Fi ScanChanged event\n"); wifi_manager_scan_state_e *scan_state = (wifi_manager_scan_state_e *)event_cb->Data; @@ -1254,6 +1336,10 @@ int _wifi_get_callback_count_from_handle_list(wifi_manager_handle_cb_e e) if (local_handle->multi_scan_cb) ++count; break; + case WIFI_NETLINK_SCAN_CB: + if (local_handle->netlink_scan_cb) + ++count; + break; default: break; } @@ -1685,6 +1771,39 @@ int _wifi_bssid_scan_request(wifi_manager_h wifi, return WIFI_MANAGER_ERROR_OPERATION_FAILED; } +int _wifi_netlink_scan_request(wifi_manager_h wifi, + wifi_manager_netlink_scan_finished_cb callback, void *user_data) +{ + int rv; + wifi_manager_device_state_e device_state; + + /** When tethering is enabled wlan interface is available but wifi device is + in deactivated state and so to search APs wifi_manager_netlink_scan() API is used. + When wifi device is in activated state use wifi_manager_scan() API instead. */ + rv = _wifi_get_wifi_device_state(&device_state); + if (rv == WIFI_MANAGER_ERROR_NONE) { + if (WIFI_MANAGER_DEVICE_STATE_ACTIVATED == device_state) { + WIFI_LOG(WIFI_ERROR, "Invalid Operation, Device state activated."); + return WIFI_MANAGER_ERROR_INVALID_OPERATION; + } + } + + rv = net_netlink_scan_wifi(); + + if (rv == NET_ERR_ACCESS_DENIED) { + WIFI_LOG(WIFI_ERROR, "Access denied"); + return WIFI_MANAGER_ERROR_PERMISSION_DENIED; + } else if (rv == NET_ERR_INVALID_OPERATION) { + return WIFI_MANAGER_ERROR_INVALID_OPERATION; + } else if (rv == NET_ERR_NONE) { + __set_netlink_scan_cb(wifi, callback, user_data); + return WIFI_MANAGER_ERROR_NONE; + } + + WIFI_LOG(WIFI_ERROR, "Operation Failed"); + return WIFI_MANAGER_ERROR_OPERATION_FAILED; +} + //LCOV_EXCL_START int _wifi_add_vsie(wifi_manager_h wifi, wifi_manager_vsie_frames_e frame_id, const char *vsie_str) @@ -2004,6 +2123,26 @@ int _wifi_foreach_found_bssid_ap(wifi_manager_found_ap_cb callback, void *user_d return WIFI_MANAGER_ERROR_NONE; } +int _wifi_foreach_found_netlink_scan_ap(wifi_manager_found_ap_cb callback, void *user_data) +{ + int rv; + GSList *list; + + if (bss_profile_iterator == NULL) { + WIFI_LOG(WIFI_ERROR, "Failed to search APs"); + return WIFI_MANAGER_ERROR_OPERATION_FAILED; + } + + for (list = bss_profile_iterator; list; list = list->next) { + net_profile_info_s *prof_info = (net_profile_info_s *)list->data; + rv = callback((wifi_manager_ap_h)prof_info, user_data); + if (rv == false) break; + } + + __clear_profile_list(&bss_profile_iterator); + return WIFI_MANAGER_ERROR_NONE; +} + int _wifi_open_profile(wifi_manager_h wifi, wifi_manager_ap_h ap_h, wifi_manager_connected_cb callback, void *user_data) { diff --git a/src/wifi_manager.c b/src/wifi_manager.c index 66c07b5..e055c0a 100755 --- a/src/wifi_manager.c +++ b/src/wifi_manager.c @@ -597,6 +597,23 @@ EXPORT_API int wifi_manager_foreach_found_bssid_ap(wifi_manager_h wifi, return _wifi_foreach_found_bssid_ap(callback, user_data); } +EXPORT_API int wifi_manager_foreach_found_netlink_scan_ap(wifi_manager_h wifi, + wifi_manager_found_ap_cb callback, void *user_data) +{ + __NETWORK_CAPI_FUNC_ENTER__; + + CHECK_FEATURE_SUPPORTED(WIFI_FEATURE); + + if (callback == NULL || !(__wifi_check_handle_validity(wifi))) { + WIFI_LOG(WIFI_ERROR, "Invalid parameter"); //LCOV_EXCL_LINE + __NETWORK_CAPI_FUNC_EXIT__; //LCOV_EXCL_LINE + return WIFI_MANAGER_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE + } + + __NETWORK_CAPI_FUNC_EXIT__; + return _wifi_foreach_found_netlink_scan_ap(callback, user_data); +} + EXPORT_API int wifi_manager_connect(wifi_manager_h wifi, wifi_manager_ap_h ap, wifi_manager_connected_cb callback, void *user_data) { @@ -1265,6 +1282,23 @@ EXPORT_API int wifi_manager_bssid_scan(wifi_manager_h wifi, return _wifi_bssid_scan_request(wifi, callback, user_data); } +EXPORT_API int wifi_manager_netlink_scan(wifi_manager_h wifi, + wifi_manager_netlink_scan_finished_cb callback, void *user_data) +{ + __NETWORK_CAPI_FUNC_ENTER__; + + CHECK_FEATURE_SUPPORTED(WIFI_FEATURE); + + if (callback == NULL || !(__wifi_check_handle_validity(wifi))) { + WIFI_LOG(WIFI_ERROR, "Invalid parameter"); + __NETWORK_CAPI_FUNC_EXIT__; //LCOV_EXCL_LINE + return WIFI_MANAGER_ERROR_INVALID_PARAMETER; + } + + __NETWORK_CAPI_FUNC_EXIT__; + return _wifi_netlink_scan_request(wifi, callback, user_data); +} + //LCOV_EXCL_START EXPORT_API int wifi_manager_add_vsie(wifi_manager_h wifi, wifi_manager_vsie_frames_e frame_id, const char *vsie_str) diff --git a/test/wifi_manager_test.c b/test/wifi_manager_test.c index d2ec2ad..5b53de2 100755 --- a/test/wifi_manager_test.c +++ b/test/wifi_manager_test.c @@ -43,6 +43,7 @@ wifi_manager_h wifi2 = NULL; gboolean test_thread(GIOChannel *source, GIOCondition condition, gpointer data); int test_wifi_manager_foreach_bssid_scan(void); +int test_wifi_manager_foreach_netlink_scan(void); static const char *__test_convert_error_to_string(wifi_manager_error_e err_type) { @@ -151,6 +152,15 @@ static void __test_bssid_scan_request_callback(wifi_manager_error_e error_code, test_wifi_manager_foreach_bssid_scan(); } +static void __test_netlink_scan_request_callback(wifi_manager_error_e error_code, void *user_data) +{ + printf("Netlink Scan Completed, error code : %s\n", + __test_convert_error_to_string(error_code)); + + if (error_code == WIFI_MANAGER_ERROR_NONE) + test_wifi_manager_foreach_netlink_scan(); +} + static void __test_connection_state_callback(wifi_manager_connection_state_e state, wifi_manager_ap_h ap, void* user_data) { int rv = 0; @@ -2485,6 +2495,84 @@ int test_wifi_manager_bssid_scan(void) return 1; } +static bool __test_get_netlink_scan_list(wifi_manager_ap_h ap, void *user_data) +{ + char *bssid = NULL; + char *essid = NULL; + char *vsie = NULL; + int freq; + int rssi; + int length; + + if (wifi_manager_ap_get_bssid(ap, &bssid) != WIFI_MANAGER_ERROR_NONE) { + printf("Failed to get bssid for ap\n"); + return false; + } + + + if (wifi_manager_ap_get_essid(ap, &essid) != WIFI_MANAGER_ERROR_NONE) { + printf("Failed to get essid for ap\n"); + g_free(bssid); + return false; + } + + if (wifi_manager_ap_get_frequency(ap, &freq) != WIFI_MANAGER_ERROR_NONE) { + printf("Fail to get Frequency\n"); + g_free(bssid); + g_free(essid); + return false; + } + + if (wifi_manager_ap_get_rssi(ap, &rssi) != WIFI_MANAGER_ERROR_NONE) { + printf("Failed to get rssi for ap\n"); + g_free(bssid); + g_free(essid); + return false; + } + + printf("%s, %d, %d, %s\n", bssid, freq, rssi, essid); + + if (wifi_manager_ap_get_vsie(ap, &vsie, &length) == WIFI_MANAGER_ERROR_NONE) { + if (strncmp(vsie, "dd", 2) == 0) { + printf("VSIE Len: %d vendor element: %s\n", length, vsie); + free(vsie); + } + } else + printf("Fail to get VSIE\n"); + + g_free(bssid); + g_free(essid); + return true; +} + +int test_wifi_manager_foreach_netlink_scan(void) +{ + int rv; + + rv = wifi_manager_foreach_found_netlink_scan_ap(wifi, + __test_get_netlink_scan_list, NULL); + if (rv != WIFI_MANAGER_ERROR_NONE) { + printf("Failed to get netlink scan list [%s]\n", + __test_convert_error_to_string(rv)); + return -1; + } + + return 1; +} + +int test_wifi_manager_netlink_scan(void) +{ + int rv = 0; + rv = wifi_manager_netlink_scan(wifi, __test_netlink_scan_request_callback, NULL); + if (rv != WIFI_MANAGER_ERROR_NONE) { + printf("Fail to request netlink scan [%s]\n", __test_convert_error_to_string(rv)); + return -1; + } + + printf("netlink Scan request succeeded\n"); + return 1; +} + int test_wifi_manager_get_scan_state(void) { int rv = 0; @@ -2861,6 +2949,7 @@ gboolean test_thread(GIOChannel *source, GIOCondition condition, gpointer data) printf("Q - Get enable or disable of Wi-Fi profile auto-connect\n"); printf("R - Set the IP conflict detection period\n"); printf("S - Get the IP conflict detection period\n"); + printf("T - Netlink Scan\n"); printf(LOG_RED "0 - Exit \n" LOG_END); printf("ENTER - Show options menu.......\n"); @@ -3031,6 +3120,9 @@ gboolean test_thread(GIOChannel *source, GIOCondition condition, gpointer data) case 'S': rv = test_wifi_manager_get_ip_conflict_period(); break; + case 'T': + rv = test_wifi_manager_netlink_scan(); + break; default: break; } -- 2.7.4