mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-09-26 14:54:35 +08:00
Modify wlan framework (#5076)
* update auto connect use sys work. * add fast connect. * update wlan cmd, support scan result report user-level callback. Co-authored-by: zetingxu <zetingxu@bestechnic.com> Co-authored-by: liu2guang <liuguang@rt-thread.com> Co-authored-by: guodi <guodi@rt-thread.com> Co-authored-by: geniusgogo <xpxyr@sina.com>
This commit is contained in:
co-authored by
zetingxu
liu2guang
guodi
geniusgogo
parent
c8c24ae7ab
commit
1e27372e3e
@@ -9,10 +9,22 @@
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
#include <wlan_mgnt.h>
|
||||
#include <wlan_cfg.h>
|
||||
#include <wlan_prot.h>
|
||||
|
||||
#define DBG_TAG "WLAN.cmd"
|
||||
#ifdef RT_WLAN_MGNT_DEBUG
|
||||
#define DBG_LVL DBG_LOG
|
||||
#else
|
||||
#define DBG_LVL DBG_INFO
|
||||
#endif /* RT_WLAN_MGNT_DEBUG */
|
||||
#include <rtdbg.h>
|
||||
|
||||
static struct rt_wlan_scan_result scan_result;
|
||||
static struct rt_wlan_info *scan_filter = RT_NULL;
|
||||
|
||||
#if defined(RT_WLAN_MANAGE_ENABLE) && defined(RT_WLAN_MSH_CMD_ENABLE)
|
||||
|
||||
struct wifi_cmd_des
|
||||
@@ -142,46 +154,192 @@ static int wifi_status(int argc, char *argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wifi_scan(int argc, char *argv[])
|
||||
|
||||
static rt_bool_t wifi_info_isequ(struct rt_wlan_info *info1, struct rt_wlan_info *info2)
|
||||
{
|
||||
struct rt_wlan_scan_result *scan_result = RT_NULL;
|
||||
struct rt_wlan_info *info = RT_NULL;
|
||||
struct rt_wlan_info filter;
|
||||
rt_bool_t is_equ = 1;
|
||||
rt_uint8_t bssid_zero[RT_WLAN_BSSID_MAX_LENGTH] = { 0 };
|
||||
|
||||
if (argc > 3)
|
||||
return -1;
|
||||
|
||||
if (argc == 3)
|
||||
if (is_equ && (info1->security != SECURITY_UNKNOWN) && (info2->security != SECURITY_UNKNOWN))
|
||||
{
|
||||
INVALID_INFO(&filter);
|
||||
SSID_SET(&filter, argv[2]);
|
||||
info = &filter;
|
||||
is_equ &= info2->security == info1->security;
|
||||
}
|
||||
if (is_equ && ((info1->ssid.len > 0) && (info2->ssid.len > 0)))
|
||||
{
|
||||
is_equ &= info1->ssid.len == info2->ssid.len;
|
||||
is_equ &= rt_memcmp(&info2->ssid.val[0], &info1->ssid.val[0], info1->ssid.len) == 0;
|
||||
}
|
||||
if (is_equ && (rt_memcmp(&info1->bssid[0], bssid_zero, RT_WLAN_BSSID_MAX_LENGTH)) &&
|
||||
(rt_memcmp(&info2->bssid[0], bssid_zero, RT_WLAN_BSSID_MAX_LENGTH)))
|
||||
{
|
||||
is_equ &= rt_memcmp(&info1->bssid[0], &info2->bssid[0], RT_WLAN_BSSID_MAX_LENGTH) == 0;
|
||||
}
|
||||
if (is_equ && info1->datarate && info2->datarate)
|
||||
{
|
||||
is_equ &= info1->datarate == info2->datarate;
|
||||
}
|
||||
if (is_equ && (info1->channel >= 0) && (info2->channel >= 0))
|
||||
{
|
||||
is_equ &= info1->channel == info2->channel;
|
||||
}
|
||||
if (is_equ && (info1->rssi < 0) && (info2->rssi < 0))
|
||||
{
|
||||
is_equ &= info1->rssi == info2->rssi;
|
||||
}
|
||||
return is_equ;
|
||||
}
|
||||
|
||||
static rt_err_t wifi_scan_result_cache(struct rt_wlan_info *info)
|
||||
{
|
||||
struct rt_wlan_info *ptable;
|
||||
rt_err_t err = RT_EOK;
|
||||
int i, insert = -1;
|
||||
rt_base_t level;
|
||||
|
||||
if ((info == RT_NULL) || (info->ssid.len == 0)) return -RT_EINVAL;
|
||||
|
||||
LOG_D("ssid:%s len:%d mac:%02x:%02x:%02x:%02x:%02x:%02x", info->ssid.val, info->ssid.len,
|
||||
info->bssid[0], info->bssid[1], info->bssid[2], info->bssid[3], info->bssid[4], info->bssid[5]);
|
||||
|
||||
/* scanning result filtering */
|
||||
level = rt_hw_interrupt_disable();
|
||||
if (scan_filter)
|
||||
{
|
||||
struct rt_wlan_info _tmp_info = *scan_filter;
|
||||
rt_hw_interrupt_enable(level);
|
||||
if (wifi_info_isequ(&_tmp_info, info) != RT_TRUE)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_hw_interrupt_enable(level);
|
||||
}
|
||||
|
||||
/* clean scan result */
|
||||
rt_wlan_scan_result_clean();
|
||||
/* scan ap info */
|
||||
scan_result = rt_wlan_scan_with_info(info);
|
||||
if (scan_result)
|
||||
/* de-duplicatio */
|
||||
for (i = 0; i < scan_result.num; i++)
|
||||
{
|
||||
int index, num;
|
||||
if ((info->ssid.len == scan_result.info[i].ssid.len) &&
|
||||
(rt_memcmp(&info->bssid[0], &scan_result.info[i].bssid[0], RT_WLAN_BSSID_MAX_LENGTH) == 0))
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
#ifdef RT_WLAN_SCAN_SORT
|
||||
if (insert >= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
/* Signal intensity comparison */
|
||||
if ((info->rssi < 0) && (scan_result.info[i].rssi < 0))
|
||||
{
|
||||
if (info->rssi > scan_result.info[i].rssi)
|
||||
{
|
||||
insert = i;
|
||||
continue;
|
||||
}
|
||||
else if (info->rssi < scan_result.info[i].rssi)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Channel comparison */
|
||||
if (info->channel < scan_result.info[i].channel)
|
||||
{
|
||||
insert = i;
|
||||
continue;
|
||||
}
|
||||
else if (info->channel > scan_result.info[i].channel)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* data rate comparison */
|
||||
if ((info->datarate > scan_result.info[i].datarate))
|
||||
{
|
||||
insert = i;
|
||||
continue;
|
||||
}
|
||||
else if (info->datarate < scan_result.info[i].datarate)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Insert the end */
|
||||
if (insert == -1)
|
||||
insert = scan_result.num;
|
||||
|
||||
if (scan_result.num >= RT_WLAN_SCAN_CACHE_NUM)
|
||||
return RT_EOK;
|
||||
|
||||
/* malloc memory */
|
||||
ptable = rt_malloc(sizeof(struct rt_wlan_info) * (scan_result.num + 1));
|
||||
if (ptable == RT_NULL)
|
||||
{
|
||||
LOG_E("wlan info malloc failed!");
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
scan_result.num ++;
|
||||
|
||||
/* copy info */
|
||||
for (i = 0; i < scan_result.num; i++)
|
||||
{
|
||||
if (i < insert)
|
||||
{
|
||||
ptable[i] = scan_result.info[i];
|
||||
}
|
||||
else if (i > insert)
|
||||
{
|
||||
ptable[i] = scan_result.info[i - 1];
|
||||
}
|
||||
else if (i == insert)
|
||||
{
|
||||
ptable[i] = *info;
|
||||
}
|
||||
}
|
||||
rt_free(scan_result.info);
|
||||
scan_result.info = ptable;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void wifi_scan_result_clean(void)
|
||||
{
|
||||
|
||||
/* If there is data */
|
||||
if (scan_result.num)
|
||||
{
|
||||
scan_result.num = 0;
|
||||
rt_free(scan_result.info);
|
||||
scan_result.info = RT_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void print_ap_info(struct rt_wlan_info *info,int index)
|
||||
{
|
||||
char *security;
|
||||
|
||||
num = scan_result->num;
|
||||
rt_kprintf(" SSID MAC security rssi chn Mbps\n");
|
||||
rt_kprintf("------------------------------- ----------------- -------------- ---- --- ----\n");
|
||||
for (index = 0; index < num; index ++)
|
||||
if(index == 0)
|
||||
{
|
||||
rt_kprintf("%-32.32s", &scan_result->info[index].ssid.val[0]);
|
||||
rt_kprintf(" SSID MAC security rssi chn Mbps\n");
|
||||
rt_kprintf("------------------------------- ----------------- -------------- ---- --- ----\n");
|
||||
}
|
||||
|
||||
{
|
||||
rt_kprintf("%-32.32s", &(info->ssid.val[0]));
|
||||
rt_kprintf("%02x:%02x:%02x:%02x:%02x:%02x ",
|
||||
scan_result->info[index].bssid[0],
|
||||
scan_result->info[index].bssid[1],
|
||||
scan_result->info[index].bssid[2],
|
||||
scan_result->info[index].bssid[3],
|
||||
scan_result->info[index].bssid[4],
|
||||
scan_result->info[index].bssid[5]
|
||||
info->bssid[0],
|
||||
info->bssid[1],
|
||||
info->bssid[2],
|
||||
info->bssid[3],
|
||||
info->bssid[4],
|
||||
info->bssid[5]
|
||||
);
|
||||
switch (scan_result->info[index].security)
|
||||
switch (info->security)
|
||||
{
|
||||
case SECURITY_OPEN:
|
||||
security = "OPEN";
|
||||
@@ -218,15 +376,85 @@ static int wifi_scan(int argc, char *argv[])
|
||||
break;
|
||||
}
|
||||
rt_kprintf("%-14.14s ", security);
|
||||
rt_kprintf("%-4d ", scan_result->info[index].rssi);
|
||||
rt_kprintf("%3d ", scan_result->info[index].channel);
|
||||
rt_kprintf("%4d\n", scan_result->info[index].datarate / 1000000);
|
||||
rt_kprintf("%-4d ", info->rssi);
|
||||
rt_kprintf("%3d ", info->channel);
|
||||
rt_kprintf("%4d\n", info->datarate / 1000000);
|
||||
}
|
||||
rt_wlan_scan_result_clean();
|
||||
}
|
||||
else
|
||||
|
||||
}
|
||||
|
||||
static void user_ap_info_callback(int event, struct rt_wlan_buff *buff, void *parameter)
|
||||
{
|
||||
struct rt_wlan_info *info = RT_NULL;
|
||||
int index = 0;
|
||||
int ret = RT_EOK;
|
||||
|
||||
RT_ASSERT(event == RT_WLAN_EVT_SCAN_REPORT);
|
||||
RT_ASSERT(buff != RT_NULL);
|
||||
RT_ASSERT(parameter != RT_NULL);
|
||||
|
||||
info = (struct rt_wlan_info *)buff->data;
|
||||
index = *((int *)(parameter));
|
||||
|
||||
ret = wifi_scan_result_cache(info);
|
||||
if(ret == RT_EOK)
|
||||
{
|
||||
rt_kprintf("wifi scan result is null\n");
|
||||
if(scan_filter == RT_NULL ||
|
||||
(scan_filter != RT_NULL &&
|
||||
scan_filter->ssid.len == info->ssid.len &&
|
||||
rt_memcmp(&scan_filter->ssid.val[0], &info->ssid.val[0], scan_filter->ssid.len) == 0))
|
||||
{
|
||||
/*Print the info*/
|
||||
print_ap_info(info,index);
|
||||
|
||||
index++;
|
||||
*((int *)(parameter)) = index;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
static int wifi_scan(int argc, char *argv[])
|
||||
{
|
||||
struct rt_wlan_info *info = RT_NULL;
|
||||
struct rt_wlan_info filter;
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
|
||||
if (argc > 3)
|
||||
return -1;
|
||||
|
||||
if (argc == 3)
|
||||
{
|
||||
INVALID_INFO(&filter);
|
||||
SSID_SET(&filter, argv[2]);
|
||||
info = &filter;
|
||||
}
|
||||
|
||||
ret = rt_wlan_register_event_handler(RT_WLAN_EVT_SCAN_REPORT,user_ap_info_callback,&i);
|
||||
if(ret != RT_EOK)
|
||||
{
|
||||
LOG_E("Scan register user callback error:%d!\n",ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(info)
|
||||
{
|
||||
scan_filter = info;
|
||||
}
|
||||
|
||||
|
||||
/*Todo: what can i do for it return val */
|
||||
ret = rt_wlan_scan_with_info(info);
|
||||
if(ret != RT_EOK)
|
||||
{
|
||||
LOG_E("Scan with info error:%d!\n",ret);
|
||||
}
|
||||
|
||||
/* clean scan result */
|
||||
wifi_scan_result_clean();
|
||||
if(info)
|
||||
{
|
||||
scan_filter = RT_NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -120,6 +120,41 @@ rt_err_t rt_wlan_dev_connect(struct rt_wlan_device *device, struct rt_wlan_info
|
||||
return result;
|
||||
}
|
||||
|
||||
rt_err_t rt_wlan_dev_fast_connect(struct rt_wlan_device *device, struct rt_wlan_info *info, const char *password, int password_len)
|
||||
{
|
||||
rt_err_t result = RT_EOK;
|
||||
struct rt_wlan_buff buff;
|
||||
|
||||
int len = 0;
|
||||
|
||||
if (device == RT_NULL)
|
||||
{
|
||||
return -RT_EIO;
|
||||
}
|
||||
if (info == RT_NULL)
|
||||
{
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
if ((password_len > RT_WLAN_PASSWORD_MAX_LENGTH) ||
|
||||
(info->ssid.len > RT_WLAN_SSID_MAX_LENGTH))
|
||||
{
|
||||
LOG_E("L:%d password or ssid is too long", __LINE__);
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
buff.len = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_GET_FAST_CONNECT_INFO, buff.data);
|
||||
if(buff.len < 0)
|
||||
{
|
||||
LOG_D("L:%d Can't get fast connect info", __LINE__);
|
||||
return buff.len;
|
||||
}
|
||||
|
||||
result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_FAST_CONNECT, &buff);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
rt_err_t rt_wlan_dev_disconnect(struct rt_wlan_device *device)
|
||||
{
|
||||
rt_err_t result = RT_EOK;
|
||||
@@ -848,6 +883,35 @@ static rt_err_t _rt_wlan_dev_control(rt_device_t dev, int cmd, void *args)
|
||||
err = wlan->ops->wlan_get_mac(wlan, mac);
|
||||
break;
|
||||
}
|
||||
case RT_WLAN_CMD_GET_FAST_CONNECT_INFO:
|
||||
{
|
||||
|
||||
LOG_D("%s %d cmd[%d]:%s run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_GET_FAST_INFO, "RT_WLAN_CMD_GET_FAST_INFO");
|
||||
if (wlan->ops->wlan_get_fast_info)
|
||||
{
|
||||
err = wlan->ops->wlan_get_fast_info(args);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = -RT_EEMPTY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RT_WLAN_CMD_FAST_CONNECT:
|
||||
{
|
||||
struct rt_wlan_buff *buff = (struct rt_wlan_buff *)args;
|
||||
LOG_D("%s %d cmd[%d]:%s run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_FAST_CONNECT, "RT_WLAN_CMD_FAST_CONNECT");
|
||||
if (wlan->ops->wlan_get_fast_info)
|
||||
{
|
||||
err = wlan->ops->wlan_fast_connect(buff->data,buff->len);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = -RT_EEMPTY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
LOG_D("%s %d cmd[%d]:%s run......", __FUNCTION__, __LINE__, -1, "UNKUOWN");
|
||||
break;
|
||||
|
||||
@@ -44,7 +44,9 @@ typedef enum
|
||||
RT_WLAN_CMD_SET_COUNTRY,
|
||||
RT_WLAN_CMD_GET_COUNTRY,
|
||||
RT_WLAN_CMD_SET_MAC,
|
||||
RT_WLAN_CMD_GET_MAC
|
||||
RT_WLAN_CMD_GET_MAC,
|
||||
RT_WLAN_CMD_GET_FAST_CONNECT_INFO,
|
||||
RT_WLAN_CMD_FAST_CONNECT,
|
||||
} rt_wlan_cmd_t;
|
||||
|
||||
typedef enum
|
||||
@@ -509,6 +511,8 @@ struct rt_wlan_dev_ops
|
||||
int (*wlan_recv)(struct rt_wlan_device *wlan, void *buff, int len);
|
||||
int (*wlan_send)(struct rt_wlan_device *wlan, void *buff, int len);
|
||||
int (*wlan_send_raw_frame)(struct rt_wlan_device *wlan, void *buff, int len);
|
||||
int (*wlan_get_fast_info)(void *data);
|
||||
rt_err_t (*wlan_fast_connect)(void *data,rt_int32_t len);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -520,6 +524,7 @@ rt_err_t rt_wlan_dev_init(struct rt_wlan_device *device, rt_wlan_mode_t mode);
|
||||
* wlan device station interface
|
||||
*/
|
||||
rt_err_t rt_wlan_dev_connect(struct rt_wlan_device *device, struct rt_wlan_info *info, const char *password, int password_len);
|
||||
rt_err_t rt_wlan_dev_fast_connect(struct rt_wlan_device *device, struct rt_wlan_info *info, const char *password, int password_len);
|
||||
rt_err_t rt_wlan_dev_disconnect(struct rt_wlan_device *device);
|
||||
int rt_wlan_dev_get_rssi(struct rt_wlan_device *device);
|
||||
|
||||
|
||||
+101
-354
File diff suppressed because it is too large
Load Diff
@@ -119,13 +119,8 @@ rt_country_code_t rt_wlan_ap_get_country(void);
|
||||
*/
|
||||
rt_err_t rt_wlan_scan(void);
|
||||
struct rt_wlan_scan_result *rt_wlan_scan_sync(void);
|
||||
struct rt_wlan_scan_result *rt_wlan_scan_with_info(struct rt_wlan_info *info);
|
||||
int rt_wlan_scan_get_info_num(void);
|
||||
int rt_wlan_scan_get_info(struct rt_wlan_info *info, int num);
|
||||
struct rt_wlan_scan_result *rt_wlan_scan_get_result(void);
|
||||
void rt_wlan_scan_result_clean(void);
|
||||
int rt_wlan_scan_find_cache(struct rt_wlan_info *info, struct rt_wlan_info *out_info, int num);
|
||||
rt_bool_t rt_wlan_find_best_by_cache(const char *ssid, struct rt_wlan_info *info);
|
||||
rt_err_t rt_wlan_scan_with_info(struct rt_wlan_info *info);
|
||||
|
||||
|
||||
/*
|
||||
* wifi auto connect interface
|
||||
|
||||
Reference in New Issue
Block a user