[wifi-manager] Added CAPI for Netlink scan. 82/160582/3
authorNiraj Kumar Goit <niraj.g@samsung.com>
Fri, 17 Nov 2017 04:19:37 +0000 (09:49 +0530)
committerNiraj Kumar Goit <niraj.g@samsung.com>
Mon, 27 Nov 2017 08:59:16 +0000 (14:29 +0530)
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 <niraj.g@samsung.com>
include/network_dbus.h
include/network_interface.h
include/network_internal.h
include/wifi_internal.h
include/wifi_manager_extension.h
src/network_dbus.c
src/network_interface.c
src/network_signal.c
src/wifi_internal.c
src/wifi_manager.c
test/wifi_manager_test.c

index 9f268ef..8795d27 100755 (executable)
@@ -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);
index 7821f93..7cf9165 100755 (executable)
@@ -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);
index 27adc8a..1547210 100755 (executable)
@@ -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,
index d0b7f6e..a8766eb 100755 (executable)
@@ -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);
index ea79196..79390df 100755 (executable)
@@ -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);
+
+/**
 * @}
 */
 
index 861c0a4..ff1bc3a 100755 (executable)
@@ -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__;
index cee2c65..9e57fb2 100755 (executable)
@@ -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__;
index 4478c5c..5496f2f 100755 (executable)
@@ -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)
index a7da0e4..ba35ee4 100755 (executable)
@@ -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)
 {
index 66c07b5..e055c0a 100755 (executable)
@@ -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)
index d2ec2ad..5b53de2 100755 (executable)
@@ -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;
        }