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);
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,
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 */
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__ */
<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
gchar* scanning_interface;
bool error_occured;
+ GList **scan_list;
} mesh_nl_state;
typedef struct {
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)
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;
mesh_nl_event_callback = handler;
mesh_nl_event_callback_data = data;
}
-#endif
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)
{
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);
}
}
// 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];
//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)
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 },
[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),
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:
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;
}
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,
.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;
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) {
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);
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)
{
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;
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;
*};
*/
- 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;
}
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);
service->dbus_id = id;
service->interface_info = g_new0(mesh_interface_s, 1);
+ service->scanned_mesh_network = NULL;
return TRUE;
}