Add functions to get scan result
authorJiwan Kim <ji-wan.kim@samsung.com>
Mon, 6 Mar 2017 06:40:00 +0000 (15:40 +0900)
committersaerome.kim <saerome.kim@samsung.com>
Mon, 17 Jul 2017 02:35:36 +0000 (11:35 +0900)
- for 'get_found_mesh_networks' method

include/mesh-netlink.h
include/mesh-request.h
include/mesh.h
introspection/mesh.xml
src/mesh-netlink.c
src/mesh-request.c
src/mesh-service-interface.c

index db9f2e9..cc55bf2 100644 (file)
@@ -28,6 +28,7 @@ int mesh_netlink_trigger_full_scan(const char* mesh_if_name);
 int mesh_netlink_trigger_specific_scan(const char* mesh_if_name,
                const char* mesh_id, int channel);
 int mesh_netlink_cancel_scan(const char* mesh_if_name);
+int mesh_netlink_get_scan_result(const char* mesh_if_name, GList **scan_list);
 int mesh_netlink_set_mesh_parameter(const char* mesh_if_name,
                const char* param_name, unsigned int value);
 
index fc70b1d..7fbab89 100644 (file)
@@ -33,6 +33,7 @@ int mesh_request_scan(const char* mesh_interface);
 int mesh_request_specific_scan(const char* mesh_interface, const char* mesh_id,
                int mesh_channel);
 int mesh_request_cancel_scan(const char* mesh_interface);
+int mesh_request_get_scan_result(const char* mesh_interface, GList **scan_list);
 
 /* Saved network */
 int mesh_request_add_mesh_network(mesh_service *service,
index ccc2048..6d65285 100644 (file)
@@ -44,6 +44,16 @@ typedef struct {
        gint mesh_channel; /**< The channel number of mesh network */
 } mesh_interface_s;
 
+/**< Mesh network scan result structure */
+typedef struct {
+       gchar *mesh_id; /**< The mesh id */
+       gint mesh_id_len; /**< Length of mesh id */
+       gchar *bssid; /**< BSSID */
+       gint rssi; /**< RSSI */
+       gint channel; /**< Channel */
+       gint data_rate; /**< Data rate */
+} mesh_scan_result_s;
+
 /**< mesh service structure */
 typedef struct _mesh_service {
        GMainLoop *main_loop; /**< Service main-loop */
@@ -52,6 +62,7 @@ typedef struct _mesh_service {
        mesh_interface_s *interface_info; /**< Name of network interfaces */
        gboolean mesh_activated; /**< Stored if mesh network is activated */
        GList *saved_mesh_network; /**< Saved mesh network list */
+       GList *scanned_mesh_network; /**< Scanned mesh network list */
 } mesh_service;
 
  #endif /* __MESH_H__ */
index 304763f..996aa12 100644 (file)
@@ -25,7 +25,7 @@
                        <arg type="u" name="result" direction="out"/>\r
                </method>\r
                <method name="get_found_mesh_networks">\r
-                       <arg type="a(a{sv})" name="network" direction="out"/>\r
+                       <arg type="aa{sv}" name="network" direction="out"/>\r
                        <arg type="u" name="result" direction="out"/>\r
                </method>\r
                <method name="enable_mesh">\r
index 2dda0cd..ae81762 100644 (file)
@@ -70,6 +70,7 @@ typedef struct {
 
        gchar* scanning_interface;
        bool error_occured;
+       GList **scan_list;
 } mesh_nl_state;
 
 typedef struct {
@@ -84,9 +85,6 @@ gboolean _handle_nl_response_message(GIOChannel *source,
        GIOCondition condition, gpointer data);
 #endif
 
-static int _send_nl_get_scan_result(const char* if_name);
-static int _on_receive_bss_information(struct nl_msg *msg, void *arg);
-
 static int __channel_to_frequency(int channel, enum nl80211_band band)
 {
        if (channel <= 0)
@@ -113,6 +111,22 @@ static int __channel_to_frequency(int channel, enum nl80211_band band)
        return 0;
 }
 
+static int __frequency_to_channel(int freq)
+{
+       if (freq == 2484)
+               return 14;
+       else if (freq < 2484)
+               return (freq - 2407) / 5;
+       else if (freq >= 4910 && freq <= 4980)
+               return (freq - 4000) / 5;
+       else if (freq <= 45000)
+               return (freq - 5000) / 5;
+       else if (freq >= 58320 && freq <= 64800)
+               return (freq - 56160) / 2160;
+       else
+               return 0;
+}
+
 static int __initialize_nl80211(mesh_nl_state *state)
 {
        int err = MESHD_ERROR_NONE;
@@ -446,7 +460,6 @@ static void register_handler(int (*handler)(struct nl_msg *, void *), void *data
        mesh_nl_event_callback = handler;
        mesh_nl_event_callback_data = data;
 }
-#endif
 
 static gboolean _dump_scan_results(gpointer user_data)
 {
@@ -462,6 +475,7 @@ static gboolean _dump_scan_results(gpointer user_data)
        g_free(if_name);
        return G_SOURCE_REMOVE;
 }
+#endif
 
 static int valid_handler(struct nl_msg *msg, void *arg)
 {
@@ -472,21 +486,15 @@ static int valid_handler(struct nl_msg *msg, void *arg)
        if (gnlh->cmd == NL80211_CMD_SCAN_ABORTED) {
                MESH_LOGD("   Got NL80211_CMD_SCAN_ABORTED.");
                state->callback_state = MESH_NL_CALLBACK_FINISHED;
-               scan_in_progress = FALSE;
 
                /* Notify scan done status */
                mesh_notify_scan_done();
        } else if (gnlh->cmd == NL80211_CMD_NEW_SCAN_RESULTS) {
-               guint id = 0;
                MESH_LOGD("   Got NL80211_CMD_NEW_SCAN_RESULTS.");
                state->callback_state = MESH_NL_CALLBACK_FINISHED;
-               scan_in_progress = FALSE;
 
                /* Notify scan done status */
                mesh_notify_scan_done();
-
-               id = g_idle_add(_dump_scan_results, g_strdup(state->scanning_interface));
-               MESH_LOGD("request scan result dump [id:%d]", id);
        } else {
                MESH_LOGD("   Got [%d]", gnlh->cmd);
        }
@@ -868,12 +876,18 @@ static void mac_addr_n2a(char *mac_addr, unsigned char *arg)
 }
 
 // ASCII
-static void print_ssid_escaped(const uint8_t len, const uint8_t *data)
+static char* _get_meshid(const uint8_t len, const uint8_t *data)
 {
        int i;
        char buf[64] = {0, };
+       char *result = g_try_malloc0(sizeof(char) * len+1);
+       if (NULL == result) {
+               MESH_LOGE("Failed to allocate");
+               return NULL;
+       }
 
        for (i = 0; i < len; i++) {
+               result[i] = data[i];
                if (/*isprint(data[i]) && */data[i] != ' ' && data[i] != '\\')
                        //printf("%c", data[i]);
                        buf[i] = data[i];
@@ -885,7 +899,10 @@ static void print_ssid_escaped(const uint8_t len, const uint8_t *data)
                        //printf("\\x%.2x", data[i]);
                        buf[i] = '?';
        }
+       result[len] = '\0';
        MESH_LOGD("  : %s", buf);
+
+       return result;
 }
 
 static int _on_receive_bss_information(struct nl_msg *msg, void *arg)
@@ -894,11 +911,14 @@ static int _on_receive_bss_information(struct nl_msg *msg, void *arg)
        struct nlattr *bss[NL80211_BSS_MAX + 1];
        struct genlmsghdr *general_header = nlmsg_data(nlmsg_hdr(msg));
        mesh_nl_state *state = (mesh_nl_state *)arg;
+       mesh_scan_result_s *scan_info = NULL;
 
        char mac_addr[20], ifname[20];
+       char *mesh_id = NULL;
+       guint mesh_id_len = 0;
        int signal_mbm = 0;
        unsigned char signal_un = 0;
-       int frequency;
+       int frequency = 0;
        int is_mesh_bss = FALSE;
        static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
                [NL80211_BSS_BSSID] = { .type = NLA_UNSPEC },
@@ -909,7 +929,10 @@ static int _on_receive_bss_information(struct nl_msg *msg, void *arg)
                [NL80211_BSS_BEACON_IES] = { .type = NLA_UNSPEC },
        };
 
-       NOTUSED(state);
+       if (NULL == state) {
+               MESH_LOGE("Invalid state data");
+               goto FINISH;
+       }
 
        nla_parse(tb, NL80211_ATTR_MAX,
                        genlmsg_attrdata(general_header, 0),
@@ -936,7 +959,8 @@ static int _on_receive_bss_information(struct nl_msg *msg, void *arg)
                        switch (ie[0]) {
                        case MESH_ELEMENT_ID: /* MESH ID */
                                MESH_LOGD("MESH ID");
-                               print_ssid_escaped(len, ie+2);
+                               mesh_id = _get_meshid(len, ie+2);
+                               mesh_id_len = len;
                                is_mesh_bss = TRUE;
                                break;
                        default:
@@ -977,9 +1001,23 @@ static int _on_receive_bss_information(struct nl_msg *msg, void *arg)
                MESH_LOGD("  signal: %d/100", signal_un);
        }
 
+       scan_info = g_try_new0(mesh_scan_result_s, 1);
+       if (NULL == scan_info) {
+               MESH_LOGE("Failed to allocate scan info !");
+               goto FINISH;
+       }
+
+       scan_info->mesh_id = g_memdup(mesh_id, mesh_id_len + 1);
+       scan_info->bssid = g_strdup(mac_addr);
+       scan_info->rssi = (signal_mbm != 0) ? signal_mbm : signal_un;
+       scan_info->channel = __frequency_to_channel(frequency);
+       scan_info->data_rate = 0;
+       *(state->scan_list) = g_list_prepend(*(state->scan_list), scan_info);
+
        MESH_LOGD("");
 
 FINISH:
+       g_free(mesh_id);
        return NL_SKIP;
 }
 
@@ -1106,7 +1144,7 @@ DESTROY:
        return err;
 }
 
-static int _send_nl_get_scan_result(const char* if_name)
+static int _send_nl_get_scan_result(const char* if_name, GList **scan_list)
 {
        mesh_nl_state state = {
                .nl80211_id = -1,
@@ -1116,7 +1154,8 @@ static int _send_nl_get_scan_result(const char* if_name)
                .msg = NULL,
                .cb = NULL,
                .s_cb = NULL,
-               .scanning_interface = (char*)if_name
+               .scanning_interface = (char*)if_name,
+               .scan_list = scan_list
        };
        int err = MESHD_ERROR_NONE;
        int device_index = 0;
@@ -1197,7 +1236,8 @@ static int _send_nl_trigger_specific_scan(const char* mesh_if_name,
        int i = 1;
        int test = 0;
        unsigned int freq = 0;
-       unsigned char mesh_ie[2];
+       unsigned char *mesh_ie = NULL;
+       size_t mesh_id_len = 0;
        GIOChannel *recv_channel = NULL;
 
        if (scan_in_progress) {
@@ -1261,20 +1301,24 @@ static int _send_nl_trigger_specific_scan(const char* mesh_if_name,
        freq = __channel_to_frequency(mesh_channel, band);
        NLA_PUT_U32(freqs, i, freq);
 
-       /* Set SSID to scan*/
-       if (mesh_id)
-               NLA_PUT(ssids, i++, strlen(mesh_id), mesh_id);
-       else
-               NLA_PUT(ssids, 1, 0, "");
+       /* Set default SSID to scan */
+       NLA_PUT(ssids, 1, 0, "");
 
        /* Set frequency and SSID into message */
        nla_put_nested(state->msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs);
        nla_put_nested(state->msg, NL80211_ATTR_SCAN_SSIDS, ssids);
 
-       /* IMPORTANT: Add mesh_id to get mesh bss properly */
+       /* IMPORTANT: Set mesh_id to find */
+       mesh_id_len = strlen(mesh_id);
+       mesh_ie = g_try_malloc0(2 + mesh_id_len);
+       if (NULL == mesh_ie) {
+               err = MESHD_ERROR_OUT_OF_MEMORY;
+               goto DESTROY;
+       }
        mesh_ie[0] = MESH_ELEMENT_ID; /* Mesh element ID */
-       mesh_ie[1] = 0;
-       NLA_PUT(state->msg, NL80211_ATTR_IE, 2, mesh_ie);
+       mesh_ie[1] = mesh_id_len;
+       memcpy(&mesh_ie[2], mesh_id, mesh_id_len);
+       NLA_PUT(state->msg, NL80211_ATTR_IE, 2 + mesh_id_len, mesh_ie);
 
        /* Set callbacks for scan */
        nl_cb_set(state->cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, state);
@@ -1708,6 +1752,31 @@ int mesh_netlink_cancel_scan(const char* mesh_if_name)
        return ret;
 }
 
+int mesh_netlink_get_scan_result(const char* mesh_if_name, GList **scan_list)
+{
+       int ret = MESHD_ERROR_NONE;
+
+       if (NULL == mesh_if_name || strlen(mesh_if_name) > IFNAMSIZ) {
+               MESH_LOGE("Invalid parameter [%p]", mesh_if_name);
+               return MESHD_ERROR_INVALID_PARAMETER;
+       }
+       if (NULL == scan_list) {
+               MESH_LOGE("Invalid parameter [%p]", scan_list);
+               return MESHD_ERROR_INVALID_PARAMETER;   
+       }
+
+       MESH_LOGD("Get scan result on [%s]", mesh_if_name);
+       ret = _send_nl_get_scan_result(mesh_if_name, scan_list);
+
+       /* List item is saved with reversed order for efficiency. */
+       *scan_list = g_list_reverse(*scan_list);
+
+       /* Enter to scan idle state */
+       scan_in_progress = FALSE;
+
+       return ret;
+}
+
 int mesh_netlink_set_mesh_parameter(const char* mesh_if_name,
                const char* param_name, unsigned int value)
 {
index 7d03d2c..67a339a 100644 (file)
@@ -111,6 +111,21 @@ int mesh_request_cancel_scan(const char* mesh_interface)
        return ret;
 }
 
+int mesh_request_get_scan_result(const char* mesh_interface, GList **scan_list)
+{
+       int ret = MESHD_ERROR_NONE;
+
+       if (NULL == mesh_interface) {
+               MESH_LOGE("Invalid parameter");
+               return MESHD_ERROR_INVALID_PARAMETER;
+       }
+
+       /* Request cancel scan */
+       ret = mesh_netlink_get_scan_result(mesh_interface, scan_list);
+
+       return ret;
+}
+
 int mesh_request_disable_mesh_gate(const char* mesh_interface)
 {
        int ret = MESHD_ERROR_NONE;
index 1477957..c9de49b 100644 (file)
@@ -293,21 +293,35 @@ static gboolean _meshd_dbus_handle_cancel_scan(NetMesh *object,
        return TRUE;
 }
 
+static void _on_scan_result_destroy(gpointer data)
+{
+       mesh_scan_result_s *scan_item = (mesh_scan_result_s *)data;
+
+       if (scan_item) {
+               g_free(scan_item->mesh_id);
+               g_free(scan_item->bssid);
+       }
+}
+
 static gboolean _meshd_dbus_handle_get_found_mesh_networks(NetMesh *object,
-               GDBusMethodInvocation *invocation)
+               GDBusMethodInvocation *invocation,
+               gpointer user_data)
 {
        int ret = MESHD_ERROR_NONE;
+       mesh_service *service = (mesh_service *)user_data;
+       mesh_interface_s *info = service->interface_info;
 
        GVariantBuilder builder;
        GVariant* networks;
+       GList *iter = NULL;
+       mesh_scan_result_s *scan_item = NULL;
 
-       MESH_LOGD("Not implemented yet !");
+       MESH_LOGD("Request to get scanned mesh network list");
 
        /* TODO: Return scan results */
-
        /*
         * struct mesh_found_network_s {
-        * char *meshid;
+        * char *mesh_id;
         * char *bssid;
         * int channel;
         * int rssi;
@@ -315,24 +329,60 @@ static gboolean _meshd_dbus_handle_get_found_mesh_networks(NetMesh *object,
         *};
         */
 
-       MESH_LOGD("Not implemented yet !");
+       ret = mesh_request_get_scan_result(info->mesh_interface, &service->scanned_mesh_network);
+       if (MESHD_ERROR_NONE != ret) {
+               MESH_LOGE("Failed to mesh_request_cancel_scan");
 
-       /* TODO: Get station infomation and make variant data */
+               g_dbus_method_invocation_return_error(invocation,
+                               G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Request Failed");
+       } else {
+               /* TODO: Get station information and make variant data */
+               g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
+
+               /* For each network item */
+               g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
+               g_variant_builder_add(&builder, "{sv}", "mesh_id", g_variant_new_string("meshnet"));
+               g_variant_builder_add(&builder, "{sv}", "bssid", g_variant_new_string("7c:dd:90:62:37:cf"));
+               g_variant_builder_add(&builder, "{sv}", "rssi", g_variant_new_uint32(-65));
+               g_variant_builder_add(&builder, "{sv}", "channel", g_variant_new_uint32(161));
+               g_variant_builder_add(&builder, "{sv}", "data_rate", g_variant_new_uint32(300));
+               g_variant_builder_close(&builder);
+
+               g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
+               g_variant_builder_add(&builder, "{sv}", "mesh_id", g_variant_new_string("meshnet"));
+               g_variant_builder_add(&builder, "{sv}", "bssid", g_variant_new_string("7c:dd:90:62:37:ce"));
+               g_variant_builder_add(&builder, "{sv}", "rssi", g_variant_new_uint32(-50));
+               g_variant_builder_add(&builder, "{sv}", "channel", g_variant_new_uint32(6));
+               g_variant_builder_add(&builder, "{sv}", "data_rate", g_variant_new_uint32(150));
+               g_variant_builder_close(&builder);
+
+               iter = service->scanned_mesh_network;
+               while (iter != NULL) {
+                       scan_item = (mesh_scan_result_s*)iter->data;
+
+                       g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
+                       g_variant_builder_add(&builder, "{sv}", "mesh_id",
+                                       g_variant_new_string(scan_item->mesh_id));
+                       g_variant_builder_add(&builder, "{sv}", "bssid",
+                                       g_variant_new_string(scan_item->bssid));
+                       g_variant_builder_add(&builder, "{sv}", "rssi",
+                                       g_variant_new_uint32(scan_item->rssi));
+                       g_variant_builder_add(&builder, "{sv}", "channel",
+                                       g_variant_new_uint32(scan_item->channel));
+                       g_variant_builder_add(&builder, "{sv}", "data_rate",
+                                       g_variant_new_uint32(scan_item->data_rate));
+                       g_variant_builder_close(&builder);
+
+                       iter = g_list_next(iter);
+               }
 
-       g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
-       g_variant_builder_add(&builder, "{sv}", "meshid", g_variant_new_string("meshnet"));
-       g_variant_builder_add(&builder, "{sv}", "bssid", g_variant_new_string("7c:dd:90:62:37:cf"));
-       g_variant_builder_add(&builder, "{sv}", "rssi", g_variant_new_uint32(-65));
-       g_variant_builder_add(&builder, "{sv}", "channel", g_variant_new_uint32(161));
-       g_variant_builder_add(&builder, "{sv}", "data_rate", g_variant_new_uint32(300));
-       g_variant_builder_add(&builder, "{sv}", "meshid", g_variant_new_string("meshnet"));
-       g_variant_builder_add(&builder, "{sv}", "bssid", g_variant_new_string("7c:dd:90:62:37:ce"));
-       g_variant_builder_add(&builder, "{sv}", "rssi", g_variant_new_uint32(-50));
-       g_variant_builder_add(&builder, "{sv}", "channel", g_variant_new_uint32(6));
-       g_variant_builder_add(&builder, "{sv}", "data_rate", g_variant_new_uint32(150));
-       networks = g_variant_builder_end(&builder);
-
-       net_mesh_complete_get_found_mesh_networks(object, invocation, networks, ret);
+               /* Clear scan list */
+               g_list_free_full(service->scanned_mesh_network, _on_scan_result_destroy);
+               service->scanned_mesh_network = NULL;
+
+               networks = g_variant_builder_end(&builder);
+               net_mesh_complete_get_found_mesh_networks(object, invocation, networks, ret);
+       }
 
        return TRUE;
 }
@@ -426,7 +476,7 @@ static gboolean _meshd_dbus_handle_set_softap(NetMesh *object,
        MESH_LOGD("key = %s", key);
        MESH_LOGD("mode = %s", mode);
        MESH_LOGD("channel = %d", channel);
-       MESH_LOGD("visibilty = %d", visibility);
+       MESH_LOGD("visibility = %d", visibility);
        MESH_LOGD("max_sta = %d", max_sta);
        MESH_LOGD("security = %d", security);
 
@@ -765,6 +815,7 @@ static gboolean _meshd_dbus_interface_init(mesh_service *service)
 
        service->dbus_id = id;
        service->interface_info = g_new0(mesh_interface_s, 1);
+       service->scanned_mesh_network = NULL;
 
        return TRUE;
 }