浏览代码

Merge pull request #1810 from enkiller/dev

[DeviceDriver][wlan] add new wlan framework
Bernard Xiong 6 年之前
父节点
当前提交
83d134bc82

+ 88 - 16
components/drivers/Kconfig

@@ -207,31 +207,103 @@ config RT_USING_WDT
     bool "Using Watch Dog device drivers"
     default n
 
-config RT_USING_WIFI
-    bool "Using Wi-Fi network"
+config RT_USING_AUDIO
+    bool "Using Audio device drivers"
+    default n
+
+menu "Using WiFi"
+    config RT_USING_WIFI
+    bool "Using Wi-Fi framework"
     default n
 
     if RT_USING_WIFI
-        config RT_USING_WLAN_STA
-            bool "Using station mode"
+        config RT_WLAN_DEVICE_STA_NAME
+            string "The WiFi device name for station"
+            default "wlan0"
+
+        config RT_WLAN_DEVICE_AP_NAME
+            string "The WiFi device name for ap"
+            default "wlan1"
+
+        config RT_WLAN_DEFAULT_PROT
+            string "Default transport protocol"
+            default "lwip"
+
+        config RT_WLAN_SCAN_WAIT_MS
+            int "Set scan timeout time(ms)"
+            default 10000;
+
+        config RT_WLAN_CONNECT_WAIT_MS
+            int "Set connect timeout time(ms)"
+            default 10000;
+
+        config RT_WLAN_SSID_MAX_LENGTH
+            int "SSID name maximum length"
+            default 32
+
+        config RT_WLAN_PASSWORD_MAX_LENGTH
+            int "Maximum password length"
+            default 32
+
+        config RT_WLAN_SCAN_SORT
+            bool "Automatic sorting of scan results"
             default y
 
-        config RT_USING_WLAN_AP
-            bool "Using ap mode"
+        config RT_WLAN_CFG_INFO_MAX
+            int "Maximum number of WiFi information automatically saved"
+            default 3
+
+        config RT_WLAN_WORKQUEUE_THREAD_NAME
+            string "WiFi work queue thread name"
+            default "wlan_job"
+
+        config RT_WLAN_WORKQUEUE_THREAD_SIZE
+            int "wifi work queue thread size"
+            default 2048
+
+        config RT_WLAN_WORKQUEUE_THREAD_PRIO
+            int "WiFi work queue thread priority"
+            default 22
+
+        config RT_WLAN_DEV_EVENT_NUM
+            int "Maximum number of driver events"
+            default 2
+
+        config RT_WLAN_PROT_LWIP_PBUF_FORCE
+            bool "Forced use of PBUF transmission"
             default n
 
-        config WIFI_DEVICE_STA_NAME
-            string "the wifi device name for station"
-            default "w0"
+        menuconfig RT_WLAN_DEBUG
+            bool "Enable WLAN Debugging Options"
+            default n
 
-        config WIFI_DEVICE_AP_NAME
-            string "the wifi device name for ap"
-            default "ap"
-    endif
+        if RT_WLAN_DEBUG
+            config RT_WLAN_CMD_DEBUG
+                bool "Enable Debugging of wlan_cmd.c"
+                default n
 
-config RT_USING_AUDIO
-    bool "Using Audio device drivers"
-    default n
+            config RT_WLAN_MGNT_DEBUG
+                bool "Enable Debugging of wlan_mgnt.c"
+                default n
+
+            config RT_WLAN_DEV_DEBUG
+                bool "Enable Debugging of wlan_dev.c"
+                default n
+
+            config RT_WLAN_PROT_DEBUG
+                bool "Enable Debugging of wlan_prot.c"
+                default n
+
+            config RT_WLAN_CFG_DEBUG
+                bool "Enable Debugging of wlan_cfg.c"
+                default n
+
+            config RT_WLAN_LWIP_DEBUG
+                bool "Enable Debugging of wlan_lwip.c"
+                default n
+        endif
+    endif
+endmenu
 
 menu "Using USB"
     config RT_USING_USB_HOST

+ 21 - 0
components/drivers/include/drivers/wlan.h

@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-09-15     tyx          the first version
+ */
+
+#ifndef __WLAN_H__
+#define __WLAN_H__
+
+#include <rtthread.h>
+#include <wlan_dev.h>
+#include <wlan_cfg.h>
+#include <wlan_mgnt.h>
+#include <wlan_prot.h>
+#include <wlan_workqueue.h>
+
+#endif

+ 6 - 16
components/drivers/include/rtdevice.h

@@ -1,21 +1,7 @@
 /*
- * File      : rtdevice.h
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team
+ * Copyright (c) 2006-2018, RT-Thread Development Team
  *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * SPDX-License-Identifier: Apache-2.0
  *
  * Change Logs:
  * Date           Author       Notes
@@ -117,6 +103,10 @@ extern "C" {
 #include "drivers/rt_drv_pwm.h"
 #endif
 
+#ifdef RT_USING_WIFI
+#include "drivers/wlan.h"
+#endif
+
 #ifdef MTD_USING_NOR
 #include "drivers/mtdnor.h"
 #endif

+ 463 - 0
components/drivers/wlan/wlan_cfg.c

@@ -0,0 +1,463 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-06     tyx          the first version
+ */
+
+#include <rtthread.h>
+#include <wlan_cfg.h>
+
+#define DBG_ENABLE
+#ifdef RT_WLAN_CFG_DEBUG
+#define DBG_LEVEL DBG_LOG
+#else
+#define DBG_LEVEL DBG_INFO
+#endif
+#define DBG_SECTION_NAME  "WLAN.cfg"
+#define DBG_COLOR
+#include <rtdbg.h>
+
+#define WLAN_CFG_LOCK()      (rt_mutex_take(&cfg_mutex, RT_WAITING_FOREVER))
+#define WLAN_CFG_UNLOCK()    (rt_mutex_release(&cfg_mutex))
+
+#if RT_WLAN_CFG_INFO_MAX < 1
+#error "The minimum configuration is 1"
+#endif
+
+struct cfg_save_info_head
+{
+    rt_uint32_t magic;
+    rt_uint32_t len;
+    rt_uint32_t num;
+    rt_uint32_t crc;
+};
+
+struct rt_wlan_cfg_des
+{
+    rt_uint32_t num;
+    struct rt_wlan_cfg_info *cfg_info;
+};
+
+static struct rt_wlan_cfg_des *cfg_cache;
+static const struct rt_wlan_cfg_ops *cfg_ops;
+static struct rt_mutex cfg_mutex;
+
+/*
+ * CRC16_CCITT
+ */
+static rt_uint16_t rt_wlan_cal_crc(rt_uint8_t *buff, int len)
+{
+    rt_uint16_t wCRCin = 0x0000;
+    rt_uint16_t wCPoly = 0x1021;
+    rt_uint8_t  wChar = 0;
+
+    while (len--)
+    {
+        wChar = *(buff++);
+        wCRCin ^= (wChar << 8);
+        for (int i = 0; i < 8; i++)
+        {
+            if (wCRCin & 0x8000)
+                wCRCin = (wCRCin << 1) ^ wCPoly;
+            else
+                wCRCin = wCRCin << 1;
+        }
+    }
+    return wCRCin;
+}
+
+void rt_wlan_cfg_init(void)
+{
+    /* init cache memory */
+    if (cfg_cache == RT_NULL)
+    {
+        cfg_cache = rt_malloc(sizeof(struct rt_wlan_cfg_des));
+        if (cfg_cache != RT_NULL)
+        {
+            rt_memset(cfg_cache, 0, sizeof(struct rt_wlan_cfg_des));
+        }
+        /* init mutex lock */
+        rt_mutex_init(&cfg_mutex, "wlan_cfg", RT_IPC_FLAG_FIFO);
+    }
+}
+
+void rt_wlan_cfg_set_ops(const struct rt_wlan_cfg_ops *ops)
+{
+    rt_wlan_cfg_init();
+
+    WLAN_CFG_LOCK();
+    /* save ops pointer */
+    cfg_ops = ops;
+    WLAN_CFG_UNLOCK();
+}
+
+/* save config data */
+rt_err_t rt_wlan_cfg_cache_save(void)
+{
+    rt_err_t err = RT_EOK;
+    struct cfg_save_info_head *info_pkg;
+    int len = 0;
+
+    if ((cfg_ops == RT_NULL) || (cfg_ops->write_cfg == RT_NULL))
+        return RT_EOK;
+
+    WLAN_CFG_LOCK();
+    len = sizeof(struct cfg_save_info_head) + sizeof(struct rt_wlan_cfg_info) * cfg_cache->num;
+    info_pkg = rt_malloc(len);
+    if (info_pkg == RT_NULL)
+    {
+        WLAN_CFG_UNLOCK();
+        return -RT_ENOMEM;
+    }
+    info_pkg->magic = RT_WLAN_CFG_MAGIC;
+    info_pkg->len = len;
+    info_pkg->num = cfg_cache->num;
+    /* CRC */
+    info_pkg->crc = rt_wlan_cal_crc((rt_uint8_t *)cfg_cache->cfg_info, sizeof(struct rt_wlan_cfg_info) * cfg_cache->num);
+    rt_memcpy(((rt_uint8_t *)info_pkg) + sizeof(struct cfg_save_info_head),
+              cfg_cache->cfg_info, sizeof(struct rt_wlan_cfg_info) * cfg_cache->num);
+    if (cfg_ops->write_cfg(info_pkg, len) != len)
+        err =  -RT_ERROR;
+    rt_free(info_pkg);
+    WLAN_CFG_UNLOCK();
+    return err;
+}
+
+rt_err_t rt_wlan_cfg_cache_refresh(void)
+{
+    int len = 0, i, j;
+    struct cfg_save_info_head *head;
+    void *data;
+    struct rt_wlan_cfg_info *t_info, *cfg_info;
+    rt_uint32_t crc;
+    rt_bool_t equal_flag;
+
+    /* cache is full! exit */
+    if (cfg_cache == RT_NULL || cfg_cache->num >= RT_WLAN_CFG_INFO_MAX)
+        return -RT_ERROR;
+
+    /* check callback */
+    if ((cfg_ops == RT_NULL) ||
+            (cfg_ops->get_len == RT_NULL) ||
+            (cfg_ops->read_cfg == RT_NULL))
+        return -RT_ERROR;
+
+    WLAN_CFG_LOCK();
+    /* get data len */
+    if ((len = cfg_ops->get_len()) <= 0)
+    {
+        WLAN_CFG_UNLOCK();
+        return -RT_ERROR;
+    }
+
+    head = rt_malloc(len);
+    if (head == RT_NULL)
+    {
+        WLAN_CFG_UNLOCK();
+        return -RT_ERROR;
+    }
+    /* get data */
+    if (cfg_ops->read_cfg(head, len) != len)
+    {
+        rt_free(head);
+        WLAN_CFG_UNLOCK();
+        return -RT_ERROR;
+    }
+    /* get config */
+    data = ((rt_uint8_t *)head) + sizeof(struct cfg_save_info_head);
+    crc = rt_wlan_cal_crc((rt_uint8_t *)data, len - sizeof(struct cfg_save_info_head));
+    LOG_D("head->magic:0x%08x  RT_WLAN_CFG_MAGIC:0x%08x", head->magic, RT_WLAN_CFG_MAGIC);
+    LOG_D("head->len:%d len:%d", head->len, len);
+    LOG_D("head->num:%d num:%d", head->num, (len - sizeof(struct cfg_save_info_head)) / sizeof(struct rt_wlan_cfg_info));
+    LOG_D("hred->crc:0x%04x crc:0x%04x", head->crc, crc);
+    /* check */
+    if ((head->magic != RT_WLAN_CFG_MAGIC) ||
+            (head->len != len) ||
+            (head->num != (len - sizeof(struct cfg_save_info_head)) / sizeof(struct rt_wlan_cfg_info)) ||
+            (head->crc != crc))
+    {
+        rt_free(head);
+        WLAN_CFG_UNLOCK();
+        return -RT_ERROR;
+    }
+
+    /* remove duplicate config */
+    cfg_info = (struct rt_wlan_cfg_info *)data;
+    for (i = 0; i < head->num; i++)
+    {
+        equal_flag = RT_FALSE;
+        for (j = 0; j < cfg_cache->num; j++)
+        {
+            if ((cfg_cache->cfg_info[j].info.ssid.len == cfg_info[i].info.ssid.len) &&
+                    (rt_memcmp(&cfg_cache->cfg_info[j].info.ssid.val[0], &cfg_info[i].info.ssid.val[0],
+                               cfg_cache->cfg_info[j].info.ssid.len) == 0) &&
+                    (rt_memcmp(&cfg_cache->cfg_info[j].info.bssid[0], &cfg_info[i].info.bssid[0], RT_WLAN_BSSID_MAX_LENGTH) == 0))
+            {
+                equal_flag = RT_TRUE;
+                break;
+            }
+        }
+
+        if (cfg_cache->num >= RT_WLAN_CFG_INFO_MAX)
+        {
+            break;
+        }
+
+        if (equal_flag == RT_FALSE)
+        {
+            t_info = rt_realloc(cfg_cache->cfg_info, sizeof(struct rt_wlan_cfg_info) * (cfg_cache->num + 1));
+            if (t_info == RT_NULL)
+            {
+                rt_free(head);
+                WLAN_CFG_UNLOCK();
+                return -RT_ERROR;
+            }
+            cfg_cache->cfg_info = t_info;
+            cfg_cache->cfg_info[cfg_cache->num] = cfg_info[i];
+            cfg_cache->num ++;
+        }
+    }
+
+    rt_free(head);
+    WLAN_CFG_UNLOCK();
+    return RT_EOK;
+}
+
+int rt_wlan_cfg_get_num(void)
+{
+    rt_wlan_cfg_init();
+
+    return cfg_cache->num;
+}
+
+int rt_wlan_cfg_read(struct rt_wlan_cfg_info *cfg_info, int num)
+{
+    rt_wlan_cfg_init();
+
+    if ((cfg_info == RT_NULL) || (num <= 0))
+        return 0;
+    /* copy data */
+    WLAN_CFG_LOCK();
+    num = cfg_cache->num > num ? num : cfg_cache->num;
+    rt_memcpy(&cfg_cache->cfg_info[0], cfg_info, sizeof(struct rt_wlan_cfg_info) * num);
+    WLAN_CFG_UNLOCK();
+
+    return num;
+}
+
+rt_err_t rt_wlan_cfg_save(struct rt_wlan_cfg_info *cfg_info)
+{
+    rt_err_t err = RT_EOK;
+    struct rt_wlan_cfg_info *t_info;
+    int idx = -1, i = 0;
+
+    rt_wlan_cfg_init();
+
+    /* parameter check */
+    if ((cfg_info == RT_NULL) || (cfg_info->info.ssid.len == 0))
+    {
+        return -RT_EINVAL;
+    }
+    /* if (iteam == cache) exit */
+    WLAN_CFG_LOCK();
+    for (i = 0; i < cfg_cache->num; i++)
+    {
+        if ((cfg_cache->cfg_info[i].info.ssid.len == cfg_info->info.ssid.len) &&
+                (rt_memcmp(&cfg_cache->cfg_info[i].info.ssid.val[0], &cfg_info->info.ssid.val[0],
+                           cfg_cache->cfg_info[i].info.ssid.len) == 0) &&
+                (rt_memcmp(&cfg_cache->cfg_info[i].info.bssid[0], &cfg_info->info.bssid[0], RT_WLAN_BSSID_MAX_LENGTH) == 0))
+        {
+            idx = i;
+            break;
+        }
+    }
+
+    if ((idx == 0) && (cfg_cache->cfg_info[i].key.len == cfg_info->key.len) &&
+            (rt_memcmp(&cfg_cache->cfg_info[i].key.val[0], &cfg_info->key.val[0], cfg_info->key.len) == 0))
+    {
+        WLAN_CFG_UNLOCK();
+        return RT_EOK;
+    }
+
+    /* not find iteam with cache, Add iteam to the head   */
+    if ((idx == -1) && (cfg_cache->num < RT_WLAN_CFG_INFO_MAX))
+    {
+        t_info = rt_realloc(cfg_cache->cfg_info, sizeof(struct rt_wlan_cfg_info) * (cfg_cache->num + 1));
+        if (t_info == RT_NULL)
+        {
+            WLAN_CFG_UNLOCK();
+            return -RT_ENOMEM;
+        }
+        cfg_cache->cfg_info = t_info;
+        cfg_cache->num ++;
+    }
+
+    /* move cache info */
+    i = (i >= RT_WLAN_CFG_INFO_MAX ? RT_WLAN_CFG_INFO_MAX - 1 : i);
+    for (; i; i--)
+    {
+        cfg_cache->cfg_info[i] = cfg_cache->cfg_info[i - 1];
+    }
+    /* add iteam to head */
+    cfg_cache->cfg_info[i] = *cfg_info;
+    WLAN_CFG_UNLOCK();
+
+    /* save info to flash */
+    err = rt_wlan_cfg_cache_save();
+
+    return err;
+}
+
+int rt_wlan_cfg_read_index(struct rt_wlan_cfg_info *cfg_info, int index)
+{
+    rt_wlan_cfg_init();
+
+    if ((cfg_info == RT_NULL) || (index < 0))
+        return 0;
+
+    WLAN_CFG_LOCK();
+    if (index >= cfg_cache->num)
+    {
+        WLAN_CFG_UNLOCK();
+        return 0;
+    }
+    /* copy data */
+    *cfg_info = cfg_cache->cfg_info[index];
+    WLAN_CFG_UNLOCK();
+    return 1;
+}
+
+int rt_wlan_cfg_delete_index(int index)
+{
+    struct rt_wlan_cfg_info *cfg_info;
+    int i;
+
+    rt_wlan_cfg_init();
+
+    if (index < 0)
+        return -1;
+
+    WLAN_CFG_LOCK();
+    if (index >= cfg_cache->num)
+    {
+        WLAN_CFG_UNLOCK();
+        return -1;
+    }
+
+    /* malloc new mem */
+    cfg_info = rt_malloc(sizeof(struct rt_wlan_cfg_info) * (cfg_cache->num - 1));
+    if (cfg_info == RT_NULL)
+    {
+        WLAN_CFG_UNLOCK();
+        return -1;
+    }
+    /* copy data to new mem */
+    for (i = 0; i < cfg_cache->num; i++)
+    {
+        if (i < index)
+        {
+            cfg_info[i] = cfg_cache->cfg_info[i];
+        }
+        else if (i > index)
+        {
+            cfg_info[i - 1] = cfg_cache->cfg_info[i];
+        }
+    }
+    rt_free(cfg_cache->cfg_info);
+    cfg_cache->cfg_info = cfg_info;
+    cfg_cache->num --;
+    WLAN_CFG_UNLOCK();
+
+    return 0;
+}
+
+void rt_wlan_cfg_delete_all(void)
+{
+    rt_wlan_cfg_init();
+
+    /* delete all iteam */
+    WLAN_CFG_LOCK();
+    cfg_cache->num = 0;
+    rt_free(cfg_cache->cfg_info);
+    cfg_cache->cfg_info = RT_NULL;
+    WLAN_CFG_UNLOCK();
+}
+
+void rt_wlan_cfg_dump(void)
+{
+    int index = 0;
+    struct rt_wlan_info *info;
+    struct rt_wlan_key *key;
+    char *security;
+
+    rt_wlan_cfg_init();
+
+    rt_kprintf("             SSID                           PASSWORD                   MAC            security     chn\n");
+    rt_kprintf("------------------------------- ------------------------------- -----------------  --------------  ---\n");
+    for (index = 0; index < cfg_cache->num; index ++)
+    {
+        info = &cfg_cache->cfg_info[index].info;
+        key = &cfg_cache->cfg_info[index].key;
+
+        if (info->ssid.len)
+            rt_kprintf("%-32.32s", &info->ssid.val[0]);
+        else
+            rt_kprintf("%-32.32s", " ");
+
+        if (key->len)
+            rt_kprintf("%-32.32s", &key->val[0]);
+        else
+            rt_kprintf("%-32.32s", " ");
+
+        rt_kprintf("%02x:%02x:%02x:%02x:%02x:%02x  ",
+                   info->bssid[0],
+                   info->bssid[1],
+                   info->bssid[2],
+                   info->bssid[3],
+                   info->bssid[4],
+                   info->bssid[5]
+                  );
+        switch (info->security)
+        {
+        case SECURITY_OPEN:
+            security = "OPEN";
+            break;
+        case SECURITY_WEP_PSK:
+            security = "WEP_PSK";
+            break;
+        case SECURITY_WEP_SHARED:
+            security = "WEP_SHARED";
+            break;
+        case SECURITY_WPA_TKIP_PSK:
+            security = "WPA_TKIP_PSK";
+            break;
+        case SECURITY_WPA_AES_PSK:
+            security = "WPA_AES_PSK";
+            break;
+        case SECURITY_WPA2_AES_PSK:
+            security = "WPA2_AES_PSK";
+            break;
+        case SECURITY_WPA2_TKIP_PSK:
+            security = "WPA2_TKIP_PSK";
+            break;
+        case SECURITY_WPA2_MIXED_PSK:
+            security = "WPA2_MIXED_PSK";
+            break;
+        case SECURITY_WPS_OPEN:
+            security = "WPS_OPEN";
+            break;
+        case SECURITY_WPS_SECURE:
+            security = "WPS_SECURE";
+            break;
+        default:
+            security = "UNKNOWN";
+            break;
+        }
+        rt_kprintf("%-14.14s  ", security);
+        rt_kprintf("%3d    \n", info->channel);
+    }
+}

+ 67 - 0
components/drivers/wlan/wlan_cfg.h

@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-06     tyx          the first version
+ */
+
+#ifndef __WLAN_CFG_H__
+#define __WLAN_CFG_H__
+
+#include <wlan_dev.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef RT_WLAN_CFG_INFO_MAX
+#define RT_WLAN_CFG_INFO_MAX    (3) /* min is 1 */
+#endif
+
+#define RT_WLAN_CFG_MAGIC       (0x426f6d62)
+
+struct rt_wlan_cfg_info
+{
+    struct rt_wlan_info info;
+    struct rt_wlan_key key;
+};
+
+typedef int (*rt_wlan_wr)(void *buff, int len);
+
+struct rt_wlan_cfg_ops
+{
+    int (*read_cfg)(void *buff, int len);
+    int (*get_len)(void);
+    int (*write_cfg)(void *buff, int len);
+};
+
+void rt_wlan_cfg_init(void);
+
+void rt_wlan_cfg_set_ops(const struct rt_wlan_cfg_ops *ops);
+
+int rt_wlan_cfg_get_num(void);
+
+int rt_wlan_cfg_read(struct rt_wlan_cfg_info *cfg_info, int num);
+
+int rt_wlan_cfg_read_index(struct rt_wlan_cfg_info *cfg_info, int index);
+
+rt_err_t rt_wlan_cfg_save(struct rt_wlan_cfg_info *cfg_info);
+
+rt_err_t rt_wlan_cfg_cache_refresh(void);
+
+rt_err_t rt_wlan_cfg_cache_save(void);
+
+int rt_wlan_cfg_delete_index(int index);
+
+void rt_wlan_cfg_delete_all(void);
+
+void rt_wlan_cfg_dump(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 428 - 389
components/drivers/wlan/wlan_cmd.c

@@ -1,527 +1,566 @@
 /*
- * File      : wlan_cmd.c
- *             Wi-Fi common commands
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+ * Copyright (c) 2006-2018, RT-Thread Development Team
  *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * SPDX-License-Identifier: Apache-2.0
  *
  * Change Logs:
  * Date           Author       Notes
- * 2016-03-12     Bernard      first version
+ * 2018-08-13     tyx          the first version
  */
 
 #include <rtthread.h>
-#include <wlan_dev.h>
-
-#include <finsh.h>
-
-#include <lwip/dhcp.h>
-#include "wlan_cmd.h"
-
-#ifdef LWIP_USING_DHCPD
-#include <dhcp_server.h>
-#endif
-
-struct rt_wlan_info info;
-static char wifi_ssid[32]    = {0};
-static char wifi_key[32]     = {0};
-static int network_mode      = WIFI_STATION;
+#include <wlan_mgnt.h>
+#include <wlan_cfg.h>
+#include <wlan_prot.h>
 
-#define WLAN_DEBUG   1
-#if WLAN_DEBUG
-#define WLAN_DBG(...)     rt_kprintf("[WLAN]"),rt_kprintf(__VA_ARGS__)
-#else
-#define WLAN_DBG(...)
-#endif
-
-#ifndef WIFI_SETTING_FN
-#define WIFI_SETTING_FN     "/appfs/setting.json"
-#endif
-
-#ifndef WIFI_DEVICE_STA_NAME
-#define WIFI_DEVICE_STA_NAME    "w0"
-#endif
-#ifndef WIFI_DEVICE_AP_NAME
-#define WIFI_DEVICE_AP_NAME    "ap"
+struct wifi_cmd_des
+{
+    const char *cmd;
+    int (*fun)(int argc, char *argv[]);
+};
+
+static int wifi_help(int argc, char *argv[]);
+static int wifi_scan(int argc, char *argv[]);
+static int wifi_status(int argc, char *argv[]);
+static int wifi_join(int argc, char *argv[]);
+static int wifi_ap(int argc, char *argv[]);
+static int wifi_list_sta(int argc, char *argv[]);
+static int wifi_disconnect(int argc, char *argv[]);
+static int wifi_ap_stop(int argc, char *argv[]);
+
+#ifdef RT_WLAN_CMD_DEBUG
+/* just for debug  */
+static int wifi_debug(int argc, char *argv[]);
+static int wifi_debug_save_cfg(int argc, char *argv[]);
+static int wifi_debug_dump_cfg(int argc, char *argv[]);
+static int wifi_debug_clear_cfg(int argc, char *argv[]);
+static int wifi_debug_dump_prot(int argc, char *argv[]);
+static int wifi_debug_set_mode(int argc, char *argv[]);
+static int wifi_debug_set_prot(int argc, char *argv[]);
+static int wifi_debug_set_autoconnect(int argc, char *argv[]);
 #endif
 
-#ifdef RT_USING_DFS
-#include <dfs_posix.h>
-#ifdef PKG_USING_CJSON
-#include <cJSON_util.h>
+/* cmd table */
+static const struct wifi_cmd_des cmd_tab[] =
+{
+    {"scan", wifi_scan},
+    {"help", wifi_help},
+    {"status", wifi_status},
+    {"join", wifi_join},
+    {"ap", wifi_ap},
+    {"list_sta", wifi_list_sta},
+    {"disc", wifi_disconnect},
+    {"ap_stop", wifi_ap_stop},
+    {"smartconfig", RT_NULL},
+#ifdef RT_WLAN_CMD_DEBUG
+    {"-d", wifi_debug},
 #endif
+};
 
-int wifi_get_mode(void)
+#ifdef RT_WLAN_CMD_DEBUG
+/* debug cmd table */
+static const struct wifi_cmd_des debug_tab[] =
 {
-    return network_mode;
-}
+    {"save_cfg", wifi_debug_save_cfg},
+    {"dump_cfg", wifi_debug_dump_cfg},
+    {"clear_cfg", wifi_debug_clear_cfg},
+    {"dump_prot", wifi_debug_dump_prot},
+    {"mode", wifi_debug_set_mode},
+    {"prot", wifi_debug_set_prot},
+    {"auto", wifi_debug_set_autoconnect},
+};
+#endif
 
-int wifi_set_mode(int mode)
+static int wifi_help(int argc, char *argv[])
 {
-    network_mode = mode;
-
-    return network_mode;
+    rt_kprintf("wifi\n");
+    rt_kprintf("wifi help\n");
+    rt_kprintf("wifi scan\n");
+    rt_kprintf("wifi join [SSID] [PASSWORD]\n");
+    rt_kprintf("wifi ap SSID [PASSWORD]\n");
+    rt_kprintf("wifi disc\n");
+    rt_kprintf("wifi ap_stop\n");
+    rt_kprintf("wifi status\n");
+    rt_kprintf("wifi smartconfig\n");
+#ifdef RT_WLAN_CMD_DEBUG
+    rt_kprintf("wifi -d debug command\n");
+#endif
+    return 0;
 }
 
-int wifi_set_setting(const char *ssid, const char *pwd)
+static int wifi_status(int argc, char *argv[])
 {
-    if (!ssid) return -1;
+    int rssi;
+    struct rt_wlan_info info;
 
-    strncpy(wifi_ssid, ssid, sizeof(wifi_ssid));
-    wifi_ssid[sizeof(wifi_ssid) - 1] = '\0';
+    if (argc > 2)
+        return -1;
 
-    if (pwd)
+    if (rt_wlan_is_connected() == 1)
     {
-        strncpy(wifi_key, pwd, sizeof(wifi_key));
-        wifi_key[sizeof(wifi_key) - 1] = '\0';
+        rssi = rt_wlan_get_rssi();
+        rt_wlan_get_info(&info);
+        rt_kprintf("Wi-Fi STA Info\n");
+        rt_kprintf("SSID : %-.32s\n", &info.ssid.val[0]);
+        rt_kprintf("MAC Addr: %02x:%02x:%02x:%02x:%02x:%02x\n", info.bssid[0],
+                   info.bssid[1],
+                   info.bssid[2],
+                   info.bssid[3],
+                   info.bssid[4],
+                   info.bssid[5]);
+        rt_kprintf("Channel: %d\n", info.channel);
+        rt_kprintf("DataRate: %dMbps\n", info.datarate / 1000000);
+        rt_kprintf("RSSI: %d\n", rssi);
+    }
+    else
+    {
+        rt_kprintf("wifi disconnected!\n");
     }
-    else wifi_key[0] = '\0';
 
+    if (rt_wlan_ap_is_active() == 1)
+    {
+        rt_wlan_ap_get_info(&info);
+        rt_kprintf("Wi-Fi AP Info\n");
+        rt_kprintf("SSID : %-.32s\n", &info.ssid.val[0]);
+        rt_kprintf("MAC Addr: %02x:%02x:%02x:%02x:%02x:%02x\n", info.bssid[0],
+                   info.bssid[1],
+                   info.bssid[2],
+                   info.bssid[3],
+                   info.bssid[4],
+                   info.bssid[5]);
+        rt_kprintf("Channel: %d\n", info.channel);
+        rt_kprintf("DataRate: %dMbps\n", info.datarate / 1000000);
+        rt_kprintf("hidden: %s\n", info.hidden ? "Enable" : "Disable");
+    }
+    else
+    {
+        rt_kprintf("wifi ap not start!\n");
+    }
+    rt_kprintf("Auto Connect status:%s!\n", (rt_wlan_get_autoreconnect_mode() ? "Enable" : "Disable"));
     return 0;
 }
 
-#ifdef PKG_USING_CJSON
-int wifi_read_cfg(const char *filename)
+static int wifi_scan(int argc, char *argv[])
 {
-    int fd;
-    cJSON *json = RT_NULL;
+    struct rt_wlan_scan_result *scan_result = RT_NULL;
 
-    fd = open(filename, O_RDONLY, 0);
-    if (fd < 0)
-    {
-        /* no setting file */
+    if (argc > 2)
         return -1;
-    }
 
-    if (fd >= 0)
+    /* scan ap info */
+    scan_result = rt_wlan_scan_sync();
+    if (scan_result)
     {
-        int length;
+        int index, num;
+        char *security;
 
-        length = lseek(fd, 0, SEEK_END);
-        if (length)
+        num = scan_result->num;
+        rt_kprintf("             SSID                      MAC            security    rssi chn Mbps\n");
+        rt_kprintf("------------------------------- -----------------  -------------- ---- --- ----\n");
+        for (index = 0; index < num; index ++)
         {
-            char *json_str = (char *) rt_malloc(length);
-            if (json_str)
+            rt_kprintf("%-32.32s", &scan_result->info[index].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]
+                      );
+            switch (scan_result->info[index].security)
             {
-                lseek(fd, 0, SEEK_SET);
-                read(fd, json_str, length);
-
-                json = cJSON_Parse(json_str);
-                rt_free(json_str);
+            case SECURITY_OPEN:
+                security = "OPEN";
+                break;
+            case SECURITY_WEP_PSK:
+                security = "WEP_PSK";
+                break;
+            case SECURITY_WEP_SHARED:
+                security = "WEP_SHARED";
+                break;
+            case SECURITY_WPA_TKIP_PSK:
+                security = "WPA_TKIP_PSK";
+                break;
+            case SECURITY_WPA_AES_PSK:
+                security = "WPA_AES_PSK";
+                break;
+            case SECURITY_WPA2_AES_PSK:
+                security = "WPA2_AES_PSK";
+                break;
+            case SECURITY_WPA2_TKIP_PSK:
+                security = "WPA2_TKIP_PSK";
+                break;
+            case SECURITY_WPA2_MIXED_PSK:
+                security = "WPA2_MIXED_PSK";
+                break;
+            case SECURITY_WPS_OPEN:
+                security = "WPS_OPEN";
+                break;
+            case SECURITY_WPS_SECURE:
+                security = "WPS_SECURE";
+                break;
+            default:
+                security = "UNKNOWN";
+                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);
         }
-        close(fd);
+        rt_wlan_scan_result_clean();
     }
-
-    if (json)
+    else
     {
-        cJSON *wifi = cJSON_GetObjectItem(json, "wifi");
-        cJSON *ssid = cJSON_GetObjectItem(wifi, "SSID");
-        cJSON *key  = cJSON_GetObjectItem(wifi, "Key");
-        cJSON *mode = cJSON_GetObjectItem(wifi, "Mode");
+        rt_kprintf("wifi scan result is null\n");
+    }
+    return 0;
+}
 
-        if (ssid)
-        {
-            memset(wifi_ssid, 0x0, sizeof(wifi_ssid));
-            rt_strncpy(wifi_ssid, ssid->valuestring, sizeof(wifi_ssid) - 1);
-        }
+static int wifi_join(int argc, char *argv[])
+{
+    const char *ssid = RT_NULL;
+    const char *key = RT_NULL;
+    struct rt_wlan_cfg_info cfg_info;
 
-        if (key)
+    if (argc ==  2)
+    {
+        /* get info to connect */
+        if (rt_wlan_cfg_read_index(&cfg_info, 0) == 1)
         {
-            memset(wifi_key, 0x0, sizeof(wifi_key));
-            rt_strncpy(wifi_key, key->valuestring, sizeof(wifi_key) - 1);
+            ssid = (char *)(&cfg_info.info.ssid.val[0]);
+            if (cfg_info.key.len)
+                key = (char *)(&cfg_info.key.val[0]);
         }
-
-        if (mode)
+        else
         {
-            network_mode = mode->valueint;
+            rt_kprintf("not find info\n");
         }
-
-        cJSON_Delete(json);
     }
-
+    else if (argc == 3)
+    {
+        /* ssid */
+        ssid = argv[2];
+    }
+    else if (argc == 4)
+    {
+        ssid = argv[2];
+        /* password */
+        key = argv[3];
+    }
+    else
+    {
+        return -1;
+    }
+    rt_wlan_connect(ssid, key);
     return 0;
 }
 
-int wifi_save_cfg(const char *filename)
+static int wifi_ap(int argc, char *argv[])
 {
-    int fd;
-    cJSON *json = RT_NULL;
+    const char *ssid = RT_NULL;
+    const char *key = RT_NULL;
 
-    fd = open(filename, O_RDONLY, 0);
-    if (fd >= 0)
+    if (argc == 3)
     {
-        int length;
-
-        length = lseek(fd, 0, SEEK_END);
-        if (length)
-        {
-            char *json_str = (char *) rt_malloc(length);
-            if (json_str)
-            {
-                lseek(fd, 0, SEEK_SET);
-                read(fd, json_str, length);
-
-                json = cJSON_Parse(json_str);
-                rt_free(json_str);
-            }
-        }
-        close(fd);
+        ssid = argv[2];
+    }
+    else if (argc == 4)
+    {
+        ssid = argv[2];
+        key = argv[3];
     }
     else
     {
-        /* create a new setting.json */
-        fd = open(filename, O_WRONLY | O_TRUNC, 0);
-        if (fd >= 0)
-        {
-            json = cJSON_CreateObject();
-            if (json)
-            {
-                cJSON *wifi = cJSON_CreateObject();
-
-                if (wifi)
-                {
-                    char *json_str;
-
-                    cJSON_AddItemToObject(json, "wifi", wifi);
-                    cJSON_AddStringToObject(wifi, "SSID", wifi_ssid);
-                    cJSON_AddStringToObject(wifi, "Key", wifi_key);
-                    cJSON_AddNumberToObject(wifi, "Mode", network_mode);
-
-                    json_str = cJSON_Print(json);
-                    if (json_str)
-                    {
-                        write(fd, json_str, rt_strlen(json_str));
-                        cJSON_free(json_str);
-                    }
-                }
-            }
-        }
-        close(fd);
-
-        return 0;
+        return -1;
     }
 
-    if (json)
-    {
-        cJSON *wifi = cJSON_GetObjectItem(json, "wifi");
-        if (!wifi)
-        {
-            wifi = cJSON_CreateObject();
-            cJSON_AddItemToObject(json, "wifi", wifi);
-        }
+    rt_wlan_start_ap(ssid, key);
+    return 0;
+}
 
-        if (cJSON_GetObjectItem(wifi, "SSID"))cJSON_ReplaceItemInObject(wifi, "SSID", cJSON_CreateString(wifi_ssid));
-        else cJSON_AddStringToObject(wifi, "SSID", wifi_ssid);
-        if (cJSON_GetObjectItem(wifi, "Key")) cJSON_ReplaceItemInObject(wifi, "Key", cJSON_CreateString(wifi_key));
-        else cJSON_AddStringToObject(wifi, "Key", wifi_key);
-        if (cJSON_GetObjectItem(wifi, "Mode")) cJSON_ReplaceItemInObject(wifi, "Mode", cJSON_CreateNumber(network_mode));
-        else cJSON_AddNumberToObject(wifi, "Mode", network_mode);
+static int wifi_list_sta(int argc, char *argv[])
+{
+    struct rt_wlan_info *sta_info;
+    int num, i;
 
-        fd = open(filename, O_WRONLY | O_TRUNC, 0);
-        if (fd >= 0)
-        {
-            char *json_str = cJSON_Print(json);
-            if (json_str)
-            {
-                write(fd, json_str, rt_strlen(json_str));
-                cJSON_free(json_str);
-            }
-            close(fd);
-        }
-        cJSON_Delete(json);
+    if (argc > 2)
+        return -1;
+    num = rt_wlan_ap_get_sta_num();
+    sta_info = rt_malloc(sizeof(struct rt_wlan_info) * num);
+    if (sta_info == RT_NULL)
+    {
+        rt_kprintf("num:%d\n", num);
+        return 0;
     }
-
+    rt_wlan_ap_get_sta_info(sta_info, num);
+    rt_kprintf("num:%d\n", num);
+    for (i = 0; i < num; i++)
+    {
+        rt_kprintf("sta mac  %02x:%02x:%02x:%02x:%02x:%02x\n",
+                   sta_info[i].bssid[0], sta_info[i].bssid[1], sta_info[i].bssid[2],
+                   sta_info[i].bssid[3], sta_info[i].bssid[4], sta_info[i].bssid[5]);
+    }
+    rt_free(sta_info);
     return 0;
 }
-#endif
 
-int wifi_save_setting(void)
+static int wifi_disconnect(int argc, char *argv[])
 {
-#ifdef PKG_USING_CJSON
-    wifi_save_cfg(WIFI_SETTING_FN);
-#endif
+    if (argc != 2)
+    {
+        return -1;
+    }
 
+    rt_wlan_disconnect();
     return 0;
 }
-#endif
 
-int wifi_softap_setup_netif(struct netif *netif)
+static int wifi_ap_stop(int argc, char *argv[])
 {
-    if (netif)
+    if (argc != 2)
     {
-#ifdef RT_LWIP_DHCP
-        /* Stop DHCP Client */
-        dhcp_stop(netif);
-#endif
-
-#ifdef LWIP_USING_DHCPD
-        {
-            char name[8];
-            memset(name, 0, sizeof(name));
-            strncpy(name, netif->name, sizeof(name) > sizeof(netif->name) ? sizeof(netif->name) : sizeof(name));
-            dhcpd_start(name);
-        }
-#endif
+        return -1;
     }
 
+    rt_wlan_ap_stop();
     return 0;
 }
 
-int wifi_default(void)
+#ifdef RT_WLAN_CMD_DEBUG
+/* just for debug */
+static int wifi_debug_help(int argc, char *argv[])
 {
-    int result = 0;
-    struct rt_wlan_device *wlan;
+    rt_kprintf("save_cfg ssid [password]\n");
+    rt_kprintf("dump_cfg\n");
+    rt_kprintf("clear_cfg\n");
+    rt_kprintf("dump_prot\n");
+    rt_kprintf("mode sta/ap dev_name\n");
+    rt_kprintf("prot lwip dev_name\n");
+    rt_kprintf("auto enable/disable\n");
+    return 0;
+}
 
-#ifdef PKG_USING_CJSON
-    /* read default setting for wifi */
-    wifi_read_cfg(WIFI_SETTING_FN);
-#endif
+static int wifi_debug_save_cfg(int argc, char *argv[])
+{
+    struct rt_wlan_cfg_info cfg_info;
+    int len;
+    char *ssid = RT_NULL, *password = RT_NULL;
 
-    if (network_mode == WIFI_STATION)
+    rt_memset(&cfg_info, 0, sizeof(cfg_info));
+    INVALID_INFO(&cfg_info.info);
+    if (argc == 2)
     {
-        /* get wlan device */
-        wlan = (struct rt_wlan_device *)rt_device_find(WIFI_DEVICE_STA_NAME);
-        if (!wlan)
-        {
-            rt_kprintf("no wlan:%s device\n", WIFI_DEVICE_STA_NAME);
-            return -1;
-        }
-
-        /* wifi station */
-        rt_wlan_info_init(&info, WIFI_STATION, SECURITY_WPA2_MIXED_PSK, wifi_ssid);
-        result = rt_wlan_init(wlan, WIFI_STATION);
-        if (result == RT_EOK)
-        {
-            result = rt_wlan_connect(wlan, &info, wifi_key);
-        }
+        ssid = argv[1];
+    }
+    else if (argc == 3)
+    {
+        ssid = argv[1];
+        password = argv[2];
     }
     else
     {
-        /* wifi AP */
-        /* get wlan device */
-        wlan = (struct rt_wlan_device *)rt_device_find(WIFI_DEVICE_AP_NAME);
-        if (!wlan)
+        return -1;
+    }
+
+    if (ssid != RT_NULL)
+    {
+        len = rt_strlen(ssid);
+        if (len > RT_WLAN_SSID_MAX_LENGTH)
         {
-            rt_kprintf("no wlan:%s device\n", WIFI_DEVICE_AP_NAME);
-            return -1;
+            rt_kprintf("ssid is to long");
+            return 0;
         }
+        rt_memcpy(&cfg_info.info.ssid.val[0], ssid, len);
+        cfg_info.info.ssid.len = len;
+    }
 
-        rt_wlan_info_init(&info, WIFI_AP, SECURITY_WPA2_AES_PSK, wifi_ssid);
-        info.channel = 11;
-
-        /* wifi soft-AP */
-        result = rt_wlan_init(wlan, WIFI_AP);
-        if (result == RT_EOK)
+    if (password != RT_NULL)
+    {
+        len = rt_strlen(password);
+        if (len > RT_WLAN_PASSWORD_MAX_LENGTH)
         {
-            result = rt_wlan_softap(wlan, &info, wifi_key);
+            rt_kprintf("password is to long");
+            return 0;
         }
+        rt_memcpy(&cfg_info.key.val[0], password, len);
+        cfg_info.key.len = len;
     }
 
-    return result;
+    rt_wlan_cfg_save(&cfg_info);
+    return 0;
 }
 
-static void wifi_usage(void)
+static int wifi_debug_dump_cfg(int argc, char *argv[])
 {
-    rt_kprintf("wifi help     - Help information\n");
-    rt_kprintf("wifi cfg SSID PASSWORD - Setting your router AP ssid and pwd\n");
-    rt_kprintf("wifi          - Do the default wifi action\n");
-    rt_kprintf("wifi wlan_dev scan\n");
-    rt_kprintf("wifi wlan_dev join SSID PASSWORD\n");
-    rt_kprintf("wifi wlan_dev ap SSID [PASSWORD]\n");
-    rt_kprintf("wifi wlan_dev up\n");
-    rt_kprintf("wifi wlan_dev down\n");
-    rt_kprintf("wifi wlan_dev rssi\n");
-    rt_kprintf("wifi wlan_dev status\n");
+    if (argc == 1)
+    {
+        rt_wlan_cfg_dump();
+    }
+    else
+    {
+        return -1;
+    }
+    return 0;
 }
 
-int wifi(int argc, char **argv)
+static int wifi_debug_clear_cfg(int argc, char *argv[])
 {
-    struct rt_wlan_device *wlan;
-
     if (argc == 1)
     {
-        wifi_default();
-        return 0;
+        rt_wlan_cfg_delete_all();
+        rt_wlan_cfg_cache_save();
     }
-
-    if (strcmp(argv[1], "help") == 0)
+    else
     {
-        wifi_usage();
-        return 0;
+        return -1;
     }
+    return 0;
+}
 
-    if (strcmp(argv[1], "cfg") == 0)
+static int wifi_debug_dump_prot(int argc, char *argv[])
+{
+    if (argc == 1)
     {
-        /* configure wifi setting */
-        memset(wifi_ssid, 0x0, sizeof(wifi_ssid));
-        rt_strncpy(wifi_ssid, argv[2], sizeof(wifi_ssid) - 1);
-
-        memset(wifi_key, 0x0, sizeof(wifi_key));
-        rt_strncpy(wifi_key, argv[3], sizeof(wifi_key) - 1);
+        rt_wlan_prot_dump();
+    }
+    else
+    {
+        return -1;
+    }
+    return 0;
+}
 
-        network_mode = WIFI_STATION;
+static int wifi_debug_set_mode(int argc, char *argv[])
+{
+    rt_wlan_mode_t mode;
 
-#ifdef PKG_USING_CJSON
-        wifi_save_cfg(WIFI_SETTING_FN);
-#endif
+    if (argc != 3)
+        return -1;
 
-        return 0;
+    if (rt_strcmp("sta", argv[1]) == 0)
+    {
+        mode = RT_WLAN_STATION;
     }
-
-    /* get wlan device */
-    wlan = (struct rt_wlan_device *)rt_device_find(argv[1]);
-    if (!wlan)
+    else if (rt_strcmp("ap", argv[1]) == 0)
     {
-        rt_kprintf("no wlan:%s device\n", argv[1]);
-        return 0;
+        mode = RT_WLAN_AP;
     }
+    else
+        return -1;
 
-    if (argc < 3)
+    rt_wlan_set_mode(argv[2], mode);
+    return 0;
+}
+
+static int wifi_debug_set_prot(int argc, char *argv[])
+{
+    if (argc != 3)
     {
-        wifi_usage();
-        return 0;
+        return -1;
     }
 
-    if (strcmp(argv[2], "join") == 0)
-    {
-        rt_wlan_init(wlan, WIFI_STATION);
-        network_mode = WIFI_STATION;
+    rt_wlan_prot_attach(argv[2], argv[1]);
+    return 0;
+}
 
-        /* TODO: use easy-join to replace */
-        rt_wlan_info_init(&info, WIFI_STATION, SECURITY_WPA2_MIXED_PSK, argv[3]);
-        rt_wlan_connect(wlan, &info, argv[4]);
-        rt_wlan_info_deinit(&info);
-    }
-    else if (strcmp(argv[2], "up") == 0)
+static int wifi_debug_set_autoconnect(int argc, char *argv[])
+{
+    if (argc == 2)
     {
-        /* the key was saved in wlan device */
-        rt_wlan_connect(wlan, RT_NULL, wlan->key);
+        if (rt_strcmp(argv[1], "enable") == 0)
+            rt_wlan_config_autoreconnect(RT_TRUE);
+        else if (rt_strcmp(argv[1], "disable") == 0)
+            rt_wlan_config_autoreconnect(RT_FALSE);
     }
-    else if (strcmp(argv[2], "down") == 0)
+    else
     {
-        rt_wlan_disconnect(wlan);
-        rt_wlan_info_deinit(&info);
+        return -1;
     }
-    else if (strcmp(argv[2], "scan") == 0)
+    return 0;
+}
+
+static int wifi_debug(int argc, char *argv[])
+{
+    int i, result = 0;
+    const struct wifi_cmd_des *run_cmd = RT_NULL;
+
+    if (argc < 3)
     {
-        struct rt_wlan_scan_result *scan_result = RT_NULL;
+        wifi_debug_help(0, RT_NULL);
+        return 0;
+    }
 
-        rt_wlan_scan(wlan, &scan_result);
-        if (scan_result)
+    for (i = 0; i < sizeof(debug_tab) / sizeof(debug_tab[0]); i++)
+    {
+        if (rt_strcmp(debug_tab[i].cmd, argv[2]) == 0)
         {
-            int index, num;
-
-            num = scan_result->ap_num;
-            rt_kprintf("             SSID                      MAC            rssi   chn    Mbps\n");
-            rt_kprintf("------------------------------- -----------------     ----   ---    ----\n");
-            for (index = 0; index < num; index ++)
-            {
-                rt_kprintf("%-32.32s", scan_result->ap_table[index].ssid);
-                rt_kprintf("%02x:%02x:%02x:%02x:%02x:%02x     ", 
-                    scan_result->ap_table[index].bssid[0],
-                    scan_result->ap_table[index].bssid[1],
-                    scan_result->ap_table[index].bssid[2],
-                    scan_result->ap_table[index].bssid[3],
-                    scan_result->ap_table[index].bssid[4],
-                    scan_result->ap_table[index].bssid[5]
-                );
-                rt_kprintf("%4d    ", scan_result->ap_table[index].rssi);
-                rt_kprintf("%2d    ", scan_result->ap_table[index].channel);
-                rt_kprintf("%d\n", scan_result->ap_table[index].datarate / 1000000);
-            }
+            run_cmd = &debug_tab[i];
+            break;
         }
-        rt_wlan_release_scan_result(&scan_result);
     }
-    else if (strcmp(argv[2], "rssi") == 0)
+
+    if (run_cmd == RT_NULL)
     {
-        int rssi;
+        wifi_debug_help(0, RT_NULL);
+        return 0;
+    }
 
-        rssi = rt_wlan_get_rssi(wlan);
-        rt_kprintf("rssi=%d\n", rssi);
+    if (run_cmd->fun != RT_NULL)
+    {
+        result = run_cmd->fun(argc - 2, &argv[2]);
     }
-    else if (strcmp(argv[2], "ap") == 0)
+
+    if (result)
     {
-        rt_err_t result = RT_EOK;
+        wifi_debug_help(argc - 2, &argv[2]);
+    }
+    return 0;
+}
+#endif
 
-        if (argc == 4)
-        {
-            // open soft-AP
-            rt_wlan_info_init(&info, WIFI_AP, SECURITY_OPEN, argv[3]);
-            info.channel = 11;
-
-            result = rt_wlan_init(wlan, WIFI_AP);
-            /* start soft ap */
-            result = rt_wlan_softap(wlan, &info, NULL);
-            if (result == RT_EOK)
-            {
-                network_mode = WIFI_AP;
-            }
-        }
-        else if (argc == 5)
-        {
-            // WPA2 with password
-            rt_wlan_info_init(&info, WIFI_AP, SECURITY_WPA2_AES_PSK, argv[3]);
-            info.channel = 11;
-
-            result = rt_wlan_init(wlan, WIFI_AP);
-            /* start soft ap */
-            result = rt_wlan_softap(wlan, &info, argv[4]);
-            if (result == RT_EOK)
-            {
-                network_mode = WIFI_AP;
-            }
-        }
-        else
-        {
-            wifi_usage();
-        }
+static int wifi_msh(int argc, char *argv[])
+{
+    int i, result = 0;
+    const struct wifi_cmd_des *run_cmd = RT_NULL;
 
-        if (result != RT_EOK)
-        {
-            rt_kprintf("wifi start failed! result=%d\n", result);
-        }
-    }
-    else if (strcmp(argv[2], "status") == 0)
+    if (argc == 1)
     {
-        int rssi;
+        wifi_help(argc, argv);
+        return 0;
+    }
 
-        if (netif_is_link_up(wlan->parent.netif))
-        {
-            rssi = rt_wlan_get_rssi(wlan);
-
-            rt_kprintf("Wi-Fi AP: %-.32s\n", wlan->info->ssid);
-            rt_kprintf("MAC Addr: %02x:%02x:%02x:%02x:%02x:%02x\n", wlan->info->bssid[0],
-                       wlan->info->bssid[1],
-                       wlan->info->bssid[2],
-                       wlan->info->bssid[3],
-                       wlan->info->bssid[4],
-                       wlan->info->bssid[5]);
-            rt_kprintf(" Channel: %d\n", wlan->info->channel);
-            rt_kprintf("DataRate: %dMbps\n", wlan->info->datarate / 1000000);
-            rt_kprintf("    RSSI: %d\n", rssi);
-        }
-        else
+    /* find fun */
+    for (i = 0; i < sizeof(cmd_tab) / sizeof(cmd_tab[0]); i++)
+    {
+        if (rt_strcmp(cmd_tab[i].cmd, argv[1]) == 0)
         {
-            rt_kprintf("wifi disconnected!\n");
+            run_cmd = &cmd_tab[i];
+            break;
         }
+    }
 
+    /* not find fun, print help */
+    if (run_cmd == RT_NULL)
+    {
+        wifi_help(argc, argv);
         return 0;
     }
 
+    /* run fun */
+    if (run_cmd->fun != RT_NULL)
+    {
+        result = run_cmd->fun(argc, argv);
+    }
+
+    if (result)
+    {
+        wifi_help(argc, argv);
+    }
     return 0;
 }
-MSH_CMD_EXPORT(wifi, wifi command);
+
+#if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH)
+FINSH_FUNCTION_EXPORT_ALIAS(wifi_msh, __cmd_wifi, wifi command.);
+#endif

+ 0 - 50
components/drivers/wlan/wlan_cmd.h

@@ -1,50 +0,0 @@
-/*
- * File      : wlan_cmd.h
- *             Wi-Fi common commands
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Change Logs:
- * Date           Author       Notes
- * 2018-06-05     RT-Thread    first version
- */
-
-#ifndef WLAN_CMD_H__
-#define WLAN_CMD_H__
-
-struct netif;
-
-int wifi_get_mode(void);
-int wifi_set_mode(int mode);
-
-/* do the wifi default action: read wifi setting and then join or start soft-AP */
-int wifi_default(void);
-/* setup netif for soft-ap */
-int wifi_softap_setup_netif(struct netif *netif);
-
-int wifi_set_setting(const char *ssid, const char *pwd);
-
-#ifdef PKG_USING_CJSON
-int wifi_read_cfg(const char *filename);
-int wifi_save_cfg(const char *filename);
-#endif
-/* save wifi setting with default storage file */
-int wifi_save_setting(void);
-
-extern struct rt_wlan_info info;
-
-#endif

+ 627 - 182
components/drivers/wlan/wlan_dev.c

@@ -1,328 +1,773 @@
 /*
- *  RT-Thread Wi-Fi Device
+ * Copyright (c) 2006-2018, RT-Thread Development Team
  *
- * COPYRIGHT (C) 2014 - 2018, Shanghai Real-Thread Technology Co., Ltd
- *
- *  This file is part of RT-Thread (http://www.rt-thread.org)
- *
- *  All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * SPDX-License-Identifier: Apache-2.0
  *
  * Change Logs:
  * Date           Author       Notes
- * 2014-09-11     Bernard      the first verion
+ * 2018-08-03     tyx          the first version
  */
 
+#include <rthw.h>
 #include <rtthread.h>
-#include <rtdevice.h>
+#include <wlan_dev.h>
+#include <wlan_prot.h>
+
+#define DBG_ENABLE
+#ifdef RT_WLAN_DEV_DEBUG
+#define DBG_LEVEL DBG_LOG
+#else
+#define DBG_LEVEL DBG_INFO
+#endif
+#define DBG_SECTION_NAME  "WLAN.dev"
+#define DBG_COLOR
+#include <rtdbg.h>
+
+#ifndef RT_DEVICE
+#define RT_DEVICE(__device) ((rt_device_t)__device)
+#endif
+
+#define WLAN_DEV_LOCK(_wlan)      (rt_mutex_take(&(_wlan)->lock, RT_WAITING_FOREVER))
+#define WLAN_DEV_UNLOCK(_wlan)    (rt_mutex_release(&(_wlan)->lock))
+
+#if RT_WLAN_SSID_MAX_LENGTH < 1
+#error "SSID length is too short"
+#endif
+
+#if RT_WLAN_BSSID_MAX_LENGTH < 1
+#error "BSSID length is too short"
+#endif
+
+#if RT_WLAN_PASSWORD_MAX_LENGTH < 1
+#error "password length is too short"
+#endif
+
+#if RT_WLAN_DEV_EVENT_NUM < 2
+#error "dev num Too little"
+#endif
+
+rt_err_t rt_wlan_dev_init(struct rt_wlan_device *device, rt_wlan_mode_t mode)
+{
+    rt_err_t result = RT_EOK;
 
-#include "wlan_dev.h"
-#include "wlan_cmd.h"
+    /* init wlan device */
+    LOG_D("F:%s L:%d is run device:0x%08x mode:%d", __FUNCTION__, __LINE__, device, mode);
+    if ((device == RT_NULL) || (mode >= RT_WLAN_MODE_MAX))
+    {
+        LOG_E("F:%s L:%d Parameter Wrongful device:0x%08x mode:%d", __FUNCTION__, __LINE__, device, mode);
+        return -RT_ERROR;
+    }
 
-#define NIOCTL_SADDR    0x02
+    result = rt_device_init(RT_DEVICE(device));
+    if (result != RT_EOK)
+    {
+        LOG_E("L:%d wlan init failed", __LINE__);
+        return -RT_ERROR;
+    }
+    result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_MODE, (void *)&mode);
+    if (result != RT_EOK)
+    {
+        LOG_E("L:%d wlan config mode failed", __LINE__);
+        return -RT_ERROR;
+    }
+    device->mode = mode;
+    return result;
+}
 
-void rt_wlan_info_init(struct rt_wlan_info *info, rt_wlan_mode_t mode, rt_wlan_security_t security,
-                       char *ssid)
+rt_err_t rt_wlan_dev_connect(struct rt_wlan_device *device, struct rt_wlan_info *info, const char *password, int password_len)
 {
-    if (info == RT_NULL) return ;
+    rt_err_t result = RT_EOK;
+    struct rt_sta_info sta_info;
 
-    memset(info, 0x0, sizeof(struct rt_wlan_info));
-    info->mode = mode;
-    info->security = security;
-    if (ssid)
+    if (device == RT_NULL)
     {
-        info->ssid = rt_malloc(strlen((char *)ssid) + 1);
-        if (info->ssid)
-        {
-            strncpy((char *)info->ssid, (char *)ssid, strlen((char *)ssid) + 1);
-        }
+        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 to long", __LINE__);
+        return -RT_ERROR;
+    }
+    rt_memset(&sta_info, 0, sizeof(struct rt_sta_info));
+    rt_memcpy(&sta_info.ssid, &info->ssid, sizeof(rt_wlan_ssid_t));
+    rt_memcpy(sta_info.bssid, info->bssid, RT_WLAN_BSSID_MAX_LENGTH);
+    if (password != RT_NULL)
+    {
+        rt_memcpy(sta_info.key.val, password, password_len);
+        sta_info.key.len = password_len;
     }
+    sta_info.channel = info->channel;
+    sta_info.security = info->security;
+
+    result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_JOIN, &sta_info);
+    return result;
 }
 
-void rt_wlan_info_deinit(struct rt_wlan_info *info)
+rt_err_t rt_wlan_dev_disconnect(struct rt_wlan_device *device)
 {
-    if (info->ssid)
+    rt_err_t result = RT_EOK;
+
+    if (device == RT_NULL)
     {
-        rt_free(info->ssid);
-        info->ssid = RT_NULL;
+        return -RT_EIO;
     }
 
-    memset(info, 0x0, sizeof(struct rt_wlan_info));
+    result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_DISCONNECT, RT_NULL);
+    return result;
 }
 
-int rt_wlan_init(struct rt_wlan_device *device, rt_wlan_mode_t mode)
+rt_err_t rt_wlan_dev_ap_start(struct rt_wlan_device *device, struct rt_wlan_info *info, const char *password, int password_len)
 {
-    int result;
+    rt_err_t result = RT_EOK;
+    struct rt_ap_info ap_info;
 
-    if (device == RT_NULL) return 0;
-
-    if (device->info == RT_NULL)
+    if (device == RT_NULL)
+    {
+        return -RT_EIO;
+    }
+    if (info == RT_NULL)
     {
-        struct rt_wlan_info *info;
-        char *ssid;
+        return -RT_ERROR;
+    }
 
-        info = rt_malloc(sizeof(struct rt_wlan_info));
-        if (info)
-        {
-            ssid = rt_malloc(SSID_LENGTH_MAX_SIZE);
-            info->ssid = ssid;
-        }
-        device->info = info;
+    if ((password_len >= RT_WLAN_PASSWORD_MAX_LENGTH) ||
+            (info->ssid.len >= RT_WLAN_SSID_MAX_LENGTH))
+    {
+        LOG_E("L:%d password or ssid is to long", __LINE__);
+        return -RT_ERROR;
     }
 
-    result = rt_device_control(RT_DEVICE(device), WIFI_INIT, (void *)&mode);
+    rt_memset(&ap_info, 0, sizeof(struct rt_ap_info));
+    rt_memcpy(&ap_info.ssid, &info->ssid, sizeof(rt_wlan_ssid_t));
+    rt_memcpy(ap_info.key.val, password, password_len);
+    ap_info.key.len = password_len;
+    ap_info.hidden = info->hidden;
+    ap_info.channel = info->channel;
+    ap_info.security = info->security;
 
+    result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_SOFTAP, &ap_info);
     return result;
 }
 
-int rt_wlan_connect(struct rt_wlan_device *device, struct rt_wlan_info *info, char *password)
+rt_err_t rt_wlan_dev_ap_stop(struct rt_wlan_device *device)
 {
-    int result = 0;
-
-    if (device == RT_NULL) return -RT_EIO;
+    rt_err_t result = RT_EOK;
 
-    if (info != RT_NULL)
+    if (device == RT_NULL)
     {
-        rt_wlan_set_info(device, info);
+        return -RT_EIO;
     }
 
-    rt_strncpy((char *)device->key, (char *)password, sizeof(device->key) - 1);
+    result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_AP_STOP, RT_NULL);
+    return result;
+}
 
-    result = rt_device_control(RT_DEVICE(device), WIFI_EASYJOIN, (void *)password);
+rt_err_t rt_wlan_dev_ap_deauth(struct rt_wlan_device *device, rt_uint8_t mac[6])
+{
+    rt_err_t result = RT_EOK;
 
+    if (device == RT_NULL)
+    {
+        return -RT_EIO;
+    }
+
+    result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_AP_DEAUTH, mac);
     return result;
 }
 
-int rt_wlan_softap(struct rt_wlan_device *device, struct rt_wlan_info *info, char *password)
+int rt_wlan_dev_get_rssi(struct rt_wlan_device *device)
 {
-    int result = RT_EOK;
-
-    if (device == RT_NULL) return -RT_EIO;
+    int rssi = 0;
 
-    if (info != RT_NULL)
+    if (device == RT_NULL)
     {
-        rt_wlan_set_info(device, info);
+        return -RT_EIO;
     }
 
-    if (password == NULL)
+    rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_GET_RSSI, &rssi);
+    return rssi;
+}
+
+rt_err_t rt_wlan_dev_get_mac(struct rt_wlan_device *device, rt_uint8_t mac[6])
+{
+    rt_err_t result = RT_EOK;
+
+    if (device == RT_NULL)
     {
-        memset(device->key, 0, sizeof(device->key));
+        return -RT_EIO;
     }
-    else
+
+    result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_GET_MAC, &mac[0]);
+    return result;
+}
+
+rt_err_t rt_wlan_dev_set_mac(struct rt_wlan_device *device, rt_uint8_t mac[6])
+{
+    rt_err_t result = RT_EOK;
+
+    if (device == RT_NULL)
     {
-        if (rt_strlen(password) > sizeof(device->key) - 1)
-        {
-            rt_kprintf("WARN input password is longer than %d bytes.", sizeof(device->key) - 1);
-        }
-        rt_strncpy((char *)device->key, (char *)password, sizeof(device->key) - 1);
+        return -RT_EIO;
     }
 
-    result = rt_device_control(RT_DEVICE(device), WIFI_SOFTAP, (void *)password);
-
+    result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_SET_MAC, &mac[0]);
     return result;
 }
 
-int rt_wlan_disconnect(struct rt_wlan_device *device)
+rt_err_t rt_wlan_dev_set_powersave(struct rt_wlan_device *device, int level)
 {
-    int result = 0;
-
-    if (device == RT_NULL) return -RT_EIO;
+    rt_err_t result = RT_EOK;
 
-    /* save event handler */
-    result = rt_device_control(RT_DEVICE(device), WIFI_DISCONNECT, RT_NULL);
+    if (device == RT_NULL)
+    {
+        return -RT_EIO;
+    }
 
+    result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_SET_POWERSAVE, &level);
     return result;
 }
 
-int rt_wlan_set_info(struct rt_wlan_device *device, struct rt_wlan_info *info)
+int rt_wlan_dev_get_powersave(struct rt_wlan_device *device)
 {
-    if (device == RT_NULL) return -RT_EIO;
-    if (device->info == RT_NULL) return -RT_EIO;
-
-    device->info->mode = info->mode;
-    device->info->security = info->security;
-    memset(device->info->ssid, 0, SSID_LENGTH_MAX_SIZE);
-    memcpy(device->info->ssid, info->ssid, strlen(info->ssid));
-    memcpy(device->info->bssid, info->bssid, 6);
-    device->info->datarate = info->datarate;
-    device->info->channel = info->channel;
-    device->info->rssi = info->rssi;
+    int level = 0;
 
-    return RT_EOK;
+    if (device == RT_NULL)
+    {
+        return -1;
+    }
+
+    rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_GET_POWERSAVE, &level);
+
+    return level;
 }
 
-struct rt_wlan_info *rt_wlan_get_info(struct rt_wlan_device *device)
+rt_err_t rt_wlan_dev_register_event_handler(struct rt_wlan_device *device, rt_wlan_dev_event_t event, rt_wlan_dev_event_handler handler, void *parameter)
 {
-    struct rt_wlan_info *info = RT_NULL;
+    int i = 0;
+    rt_base_t level;
 
-    if (device != RT_NULL)
+    if (device == RT_NULL)
+    {
+        return -RT_EIO;
+    }
+    if (event >= RT_WLAN_DEV_EVT_MAX)
     {
-        info = device->info;
+        return -RT_EINVAL;
+    }
+
+    level = rt_hw_interrupt_disable();
+    for (i = 0; i < RT_WLAN_DEV_EVENT_NUM; i++)
+    {
+        if (device->handler_table[event][i].handler == RT_NULL)
+        {
+            device->handler_table[event][i].handler = handler;
+            device->handler_table[event][i].parameter = parameter;
+            rt_hw_interrupt_enable(level);
+            return RT_EOK;
+        }
     }
+    rt_hw_interrupt_enable(level);
 
-    return info;
+    /* No space found */
+    return -RT_ERROR;
 }
 
-int rt_wlan_scan(struct rt_wlan_device *device, struct rt_wlan_scan_result **scan_result)
+rt_err_t rt_wlan_dev_unregister_event_handler(struct rt_wlan_device *device, rt_wlan_dev_event_t event, rt_wlan_dev_event_handler handler)
 {
-    int result;
+    int i = 0;
+    rt_base_t level;
 
-    result = rt_device_control(RT_DEVICE(device), WIFI_SCAN, scan_result);
+    if (device == RT_NULL)
+    {
+        return -RT_EIO;
+    }
+    if (event >= RT_WLAN_DEV_EVT_MAX)
+    {
+        return -RT_EINVAL;
+    }
 
-    return result;
+    level = rt_hw_interrupt_disable();
+    for (i = 0; i < RT_WLAN_DEV_EVENT_NUM; i++)
+    {
+        if (device->handler_table[event][i].handler == handler)
+        {
+            rt_memset(&device->handler_table[event][i], 0, sizeof(struct rt_wlan_dev_event_desc));
+            rt_hw_interrupt_enable(level);
+            return RT_EOK;
+        }
+    }
+    rt_hw_interrupt_enable(level);
+    /* not find iteam */
+    return -RT_ERROR;
 }
 
-int rt_wlan_get_rssi(struct rt_wlan_device *device)
+void rt_wlan_dev_indicate_event_handle(struct rt_wlan_device *device, rt_wlan_dev_event_t event, struct rt_wlan_buff *buff)
 {
-    int rssi;
-    int result;
+    void *parameter[RT_WLAN_DEV_EVENT_NUM];
+    rt_wlan_dev_event_handler handler[RT_WLAN_DEV_EVENT_NUM];
+    int i;
+    rt_base_t level;
+
+    if (device == RT_NULL)
+    {
+        return;
+    }
+    if (event >= RT_WLAN_DEV_EVT_MAX)
+    {
+        return;
+    }
 
-    if (device == RT_NULL) return 0;
-    result = rt_device_control(RT_DEVICE(device), WIFI_GET_RSSI, (void *)&rssi);
+    /* get callback handle */
+    level = rt_hw_interrupt_disable();
+    for (i = 0; i < RT_WLAN_DEV_EVENT_NUM; i++)
+    {
+        handler[i] = device->handler_table[event][i].handler;
+        parameter[i] = device->handler_table[event][i].parameter;
+    }
+    rt_hw_interrupt_enable(level);
 
-    if (result == RT_EOK) return rssi;
+    /* run callback */
+    for (i = 0; i < RT_WLAN_DEV_EVENT_NUM; i++)
+    {
+        if (handler[i] != RT_NULL)
+        {
+            handler[i](device, event, buff, parameter[i]);
+        }
+    }
+}
 
+rt_err_t rt_wlan_dev_enter_promisc(struct rt_wlan_device *device)
+{
+    rt_err_t result = RT_EOK;
+    int enable = 1;
+
+    if (device == RT_NULL)
+    {
+        return -RT_EIO;
+    }
+
+    result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_CFG_PROMISC, &enable);
     return result;
 }
 
-int rt_wlan_get_mac(struct rt_wlan_device *device, rt_uint8_t hwaddr[6])
+rt_err_t rt_wlan_dev_exit_promisc(struct rt_wlan_device *device)
 {
-    int result;
-    if (device == RT_NULL) return 0;
-    result = rt_device_control(RT_DEVICE(device), NIOCTL_GADDR, (void *)hwaddr);
+    rt_err_t result = RT_EOK;
+    int enable = 0;
+
+    if (device == RT_NULL)
+    {
+        return -RT_EIO;
+    }
+
+    result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_CFG_PROMISC, &enable);
     return result;
 }
 
-int rt_wlan_set_mac(struct rt_wlan_device *device, rt_uint8_t hwaddr[6])
+rt_err_t rt_wlan_dev_set_promisc_callback(struct rt_wlan_device *device, rt_wlan_pormisc_callback_t callback)
 {
-    int result;
-    if (device == RT_NULL) return 0;
-    result = rt_device_control(RT_DEVICE(device), NIOCTL_SADDR, (void *)hwaddr);
-    return result;
+    if (device == RT_NULL)
+    {
+        return -RT_EIO;
+    }
+    device->pormisc_callback = callback;
+
+    return RT_EOK;
 }
 
-int rt_wlan_enter_powersave(struct rt_wlan_device *device, int level)
+void rt_wlan_dev_promisc_handler(struct rt_wlan_device *device, void *data, int len)
 {
-    int result = 0;
+    rt_wlan_pormisc_callback_t callback;
+
+    if (device == RT_NULL)
+    {
+        return;
+    }
+
+    callback = device->pormisc_callback;
+
+    if (callback != RT_NULL)
+    {
+        callback(device, data, len);
+    }
+}
 
-    if (device == RT_NULL) return -RT_EIO;
+rt_err_t rt_wlan_dev_cfg_filter(struct rt_wlan_device *device, struct rt_wlan_filter *filter)
+{
+    rt_err_t result = RT_EOK;
 
-    result = rt_device_control(RT_DEVICE(device), WIFI_ENTER_POWERSAVE, (void *)&level);
+    if (device == RT_NULL)
+    {
+        return -RT_EIO;
+    }
+    if (filter == RT_NULL)
+    {
+        return -RT_ERROR;
+    }
 
+    result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_CFG_FILTER, filter);
     return result;
 }
 
-int rt_wlan_register_event_handler(struct rt_wlan_device *device, rt_wlan_event_t event,
-                                   rt_wlan_event_handler handler)
+rt_err_t rt_wlan_dev_set_channel(struct rt_wlan_device *device, int channel)
 {
-    if (device == RT_NULL) return -RT_EIO;
-    if (event >= WIFI_EVT_MAX) return -RT_EINVAL;
+    rt_err_t result = RT_EOK;
 
-    device->handler[event] = handler;
+    if (device == RT_NULL)
+    {
+        return -RT_EIO;
+    }
+    if (channel < 0)
+    {
+        return -RT_ERROR;
+    }
 
-    return RT_EOK;
+    result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_SET_CHANNEL, &channel);
+    return result;
 }
 
-int rt_wlan_unregister_event_handler(struct rt_wlan_device *device, rt_wlan_event_t event)
+rt_err_t rt_wlan_dev_get_channel(struct rt_wlan_device *device)
 {
-    if (device == RT_NULL) return -RT_EIO;
-    if (event >= WIFI_EVT_MAX) return -RT_EINVAL;
+    rt_err_t result = RT_EOK;
+    int channel;
 
-    device->handler[event] = RT_NULL;
+    if (device == RT_NULL)
+    {
+        return -RT_EIO;
+    }
 
-    return RT_EOK;
+    result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_GET_CHANNEL, &channel);
+    if (result != RT_EOK)
+    {
+        return -1;
+    }
+
+    return channel;
 }
 
-int rt_wlan_indicate_event_handle(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data)
+rt_err_t rt_wlan_dev_set_country(struct rt_wlan_device *device, rt_country_code_t country_code)
 {
-    if (device == RT_NULL) return -RT_EIO;
-    if (event >= WIFI_EVT_MAX) return -RT_EINVAL;
+    int result = RT_EOK;
 
-    if (device->handler[event] != RT_NULL)
-        device->handler[event](device, event, user_data);
+    if (device == RT_NULL)
+    {
+        return -RT_EIO;
+    }
 
-    return RT_EOK;
+    result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_SET_COUNTRY, &country_code);
+    return result;
 }
 
-int rt_wlan_cfg_monitor(struct rt_wlan_device *device, rt_wlan_monitor_opition_t opition)
+rt_country_code_t rt_wlan_dev_get_country(struct rt_wlan_device *device)
 {
     int result = 0;
+    rt_country_code_t country_code = RT_COUNTRY_UNKNOWN;
 
-    if (device == RT_NULL) return -RT_EIO;
+    if (device == RT_NULL)
+    {
+        return country_code;
+    }
 
-    result = rt_device_control(RT_DEVICE(device), WIFI_CFG_MONITOR, (void *)&opition);
+    result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_GET_COUNTRY, &country_code);
+    if (result != RT_EOK)
+    {
+        return RT_COUNTRY_UNKNOWN;
+    }
 
-    return result;
+    return country_code;
 }
 
-int rt_wlan_set_monitor_callback(struct rt_wlan_device *device, rt_wlan_monitor_callback_t callback)
+rt_err_t rt_wlan_dev_scan(struct rt_wlan_device *device, struct rt_wlan_info *info)
 {
-    int result = 0;
+    struct rt_scan_info scan_info = { 0 };
+    struct rt_scan_info *p_scan_info = RT_NULL;
+    rt_err_t result = 0;
+
+    if (device == RT_NULL)
+    {
+        return -RT_EIO;
+    }
 
-    if (device == RT_NULL) return -RT_EIO;
+    if (info != RT_NULL)
+    {
+        if (info->ssid.len >= RT_WLAN_SSID_MAX_LENGTH)
+        {
+            LOG_E("L:%d ssid is to long", __LINE__);
+            return -RT_EINVAL;
+        }
+        rt_memcpy(&scan_info.ssid, &info->ssid, sizeof(rt_wlan_ssid_t));
+        rt_memcpy(scan_info.bssid, info->bssid, RT_WLAN_BSSID_MAX_LENGTH);
+        scan_info.channel_min = -1;
+        scan_info.channel_max = -1;
+        p_scan_info = &scan_info;
+    }
+    result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_SCAN, p_scan_info);
+    return result;
+}
 
-    result = rt_device_control(RT_DEVICE(device), WIFI_SET_MONITOR_CALLBACK, (void *)callback);
+rt_err_t rt_wlan_dev_scan_stop(struct rt_wlan_device *device)
+{
+    rt_err_t result = 0;
 
+    if (device == RT_NULL)
+    {
+        return -RT_EIO;
+    }
+
+    result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_SCAN_STOP, RT_NULL);
     return result;
 }
 
-int rt_wlan_set_channel(struct rt_wlan_device *device, int channel)
+rt_err_t rt_wlan_dev_report_data(struct rt_wlan_device *device, void *buff, int len)
 {
-    int result = 0;
+    return rt_wlan_dev_transfer_prot(device, buff, len);
+}
 
-    if (device == RT_NULL) return -RT_EIO;
+static rt_err_t _rt_wlan_dev_init(rt_device_t dev)
+{
+    struct rt_wlan_device *wlan = (struct rt_wlan_device *)dev;
+    rt_err_t result = RT_EOK;
+
+    rt_mutex_init(&wlan->lock, "wlan_dev", RT_IPC_FLAG_FIFO);
 
-    result = rt_device_control(RT_DEVICE(device), WIFI_SET_CHANNEL, (void *)&channel);
+    if (wlan->ops->wlan_init)
+        result = wlan->ops->wlan_init(wlan);
+
+    if (result == RT_EOK)
+    {
+        LOG_I("wlan init success");
+    }
+    else
+    {
+        LOG_I("wlan init failed");
+    }
 
     return result;
 }
 
-int rt_wlan_get_channel(struct rt_wlan_device *device)
+static rt_err_t _rt_wlan_dev_control(rt_device_t dev, int cmd, void *args)
 {
-    int channel = 0;
+    struct rt_wlan_device *wlan = (struct rt_wlan_device *)dev;
+    rt_err_t err = RT_EOK;
 
-    if (device == RT_NULL) return -RT_EIO;
+    RT_ASSERT(dev != RT_NULL);
 
-    rt_device_control(RT_DEVICE(device), WIFI_GET_CHANNEL, &channel);
+    WLAN_DEV_LOCK(wlan);
 
-    return channel;
+    switch (cmd)
+    {
+    case RT_WLAN_CMD_MODE:
+    {
+        rt_wlan_mode_t mode = *((rt_wlan_mode_t *)args);
+
+        LOG_D("%s %d cmd[%d]:%s  run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_MODE, "RT_WLAN_CMD_MODE");
+        if (wlan->ops->wlan_mode)
+            err = wlan->ops->wlan_mode(wlan, mode);
+        break;
+    }
+    case RT_WLAN_CMD_SCAN:
+    {
+        struct rt_scan_info *scan_info = args;
+
+        LOG_D("%s %d cmd[%d]:%s  run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_SCAN, "RT_WLAN_CMD_SCAN");
+        if (wlan->ops->wlan_scan)
+            err = wlan->ops->wlan_scan(wlan, scan_info);
+        break;
+    }
+    case RT_WLAN_CMD_JOIN:
+    {
+        struct rt_sta_info *sta_info = args;
+
+        LOG_D("%s %d cmd[%d]:%s  run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_JOIN, "RT_WLAN_CMD_JOIN");
+        if (wlan->ops->wlan_join)
+            err = wlan->ops->wlan_join(wlan, sta_info);
+        break;
+    }
+    case RT_WLAN_CMD_SOFTAP:
+    {
+        struct rt_ap_info *ap_info = args;
+
+        LOG_D("%s %d cmd[%d]:%s  run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_SOFTAP, "RT_WLAN_CMD_SOFTAP");
+        if (wlan->ops->wlan_softap)
+            err = wlan->ops->wlan_softap(wlan, ap_info);
+        break;
+    }
+    case RT_WLAN_CMD_DISCONNECT:
+    {
+        LOG_D("%s %d cmd[%d]:%s  run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_DISCONNECT, "RT_WLAN_CMD_DISCONNECT");
+        if (wlan->ops->wlan_disconnect)
+            err = wlan->ops->wlan_disconnect(wlan);
+        break;
+    }
+    case RT_WLAN_CMD_AP_STOP:
+    {
+        LOG_D("%s %d cmd[%d]:%s  run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_AP_STOP, "RT_WLAN_CMD_AP_STOP");
+        if (wlan->ops->wlan_ap_stop)
+            err = wlan->ops->wlan_ap_stop(wlan);
+        break;
+    }
+    case RT_WLAN_CMD_AP_DEAUTH:
+    {
+        LOG_D("%s %d cmd[%d]:%s  run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_AP_DEAUTH, "RT_WLAN_CMD_AP_DEAUTH");
+        if (wlan->ops->wlan_ap_deauth)
+            err = wlan->ops->wlan_ap_deauth(wlan, args);
+        break;
+    }
+    case RT_WLAN_CMD_SCAN_STOP:
+    {
+        LOG_D("%s %d cmd[%d]:%s  run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_SCAN_STOP, "RT_WLAN_CMD_SCAN_STOP");
+        if (wlan->ops->wlan_scan_stop)
+            err = wlan->ops->wlan_scan_stop(wlan);
+        break;
+    }
+    case RT_WLAN_CMD_GET_RSSI:
+    {
+        int *rssi = args;
+
+        LOG_D("%s %d cmd[%d]:%s  run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_GET_RSSI, "RT_WLAN_CMD_GET_RSSI");
+        if (wlan->ops->wlan_get_rssi)
+            *rssi = wlan->ops->wlan_get_rssi(wlan);
+        break;
+    }
+    case RT_WLAN_CMD_SET_POWERSAVE:
+    {
+        int level = *((int *)args);
+
+        LOG_D("%s %d cmd[%d]:%s  run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_POWERSAVE, "RT_WLAN_CMD_SET_POWERSAVE");
+        if (wlan->ops->wlan_set_powersave)
+            wlan->ops->wlan_set_powersave(wlan, level);
+        break;
+    }
+    case RT_WLAN_CMD_GET_POWERSAVE:
+    {
+        int *level = args;
+
+        LOG_D("%s %d cmd[%d]:%s  run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_POWERSAVE, "RT_WLAN_CMD_GET_POWERSAVE");
+        if (wlan->ops->wlan_get_powersave)
+            *level = wlan->ops->wlan_get_powersave(wlan);
+        break;
+    }
+    case RT_WLAN_CMD_CFG_PROMISC:
+    {
+        rt_bool_t start = *((rt_bool_t *)args);
+
+        LOG_D("%s %d cmd[%d]:%s  run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_CFG_PROMISC, "RT_WLAN_CMD_CFG_PROMISC");
+        if (wlan->ops->wlan_cfg_promisc)
+            wlan->ops->wlan_cfg_promisc(wlan, start);
+        break;
+    }
+    case RT_WLAN_CMD_CFG_FILTER:
+    {
+        struct rt_wlan_filter *filter = args;
+
+        LOG_D("%s %d cmd[%d]:%s  run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_CFG_FILTER, "RT_WLAN_CMD_CFG_FILTER");
+        if (wlan->ops->wlan_cfg_filter)
+            wlan->ops->wlan_cfg_filter(wlan, filter);
+        break;
+    }
+    case RT_WLAN_CMD_SET_CHANNEL:
+    {
+        int channel = *(int *)args;
+        LOG_D("%s %d cmd[%d]:%s  run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_SET_CHANNEL, "RT_WLAN_CMD_SET_CHANNEL");
+        if (wlan->ops->wlan_set_channel)
+            wlan->ops->wlan_set_channel(wlan, channel);
+        break;
+    }
+    case RT_WLAN_CMD_GET_CHANNEL:
+    {
+        int *channel = args;
+
+        LOG_D("%s %d cmd[%d]:%s  run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_GET_CHANNEL, "RT_WLAN_CMD_GET_CHANNEL");
+        if (wlan->ops->wlan_get_channel)
+            *channel = wlan->ops->wlan_get_channel(wlan);
+        break;
+    }
+    case RT_WLAN_CMD_SET_COUNTRY:
+    {
+        rt_country_code_t country = *(rt_country_code_t *)args;
+
+        LOG_D("%s %d cmd[%d]:%s  run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_SET_COUNTRY, "RT_WLAN_CMD_SET_COUNTRY");
+        if (wlan->ops->wlan_set_country)
+            wlan->ops->wlan_set_country(wlan, country);
+        break;
+    }
+    case RT_WLAN_CMD_GET_COUNTRY:
+    {
+        rt_country_code_t *country = args;
+        LOG_D("%s %d cmd[%d]:%s  run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_GET_COUNTRY, "RT_WLAN_CMD_GET_COUNTRY");
+        if (wlan->ops->wlan_get_country)
+            *country = wlan->ops->wlan_get_country(wlan);
+        break;
+    }
+    case RT_WLAN_CMD_SET_MAC:
+    {
+        rt_uint8_t *mac = args;
+
+        LOG_D("%s %d cmd[%d]:%s  run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_SET_MAC, "RT_WLAN_CMD_SET_MAC");
+        if (wlan->ops->wlan_set_mac)
+            wlan->ops->wlan_set_mac(wlan, mac);
+        break;
+    }
+    case RT_WLAN_CMD_GET_MAC:
+    {
+        rt_uint8_t *mac = args;
+
+        LOG_D("%s %d cmd[%d]:%s  run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_GET_MAC, "RT_WLAN_CMD_GET_MAC");
+        if (wlan->ops->wlan_get_mac)
+            wlan->ops->wlan_get_mac(wlan, mac);
+        break;
+    }
+    default:
+        LOG_D("%s %d cmd[%d]:%s  run......", __FUNCTION__, __LINE__, -1, "UNKUOWN");
+        break;
+    }
+
+    WLAN_DEV_UNLOCK(wlan);
+
+    return err;
 }
 
-void rt_wlan_release_scan_result(struct rt_wlan_scan_result **scan_result)
+struct rt_wlan_device *rt_wlan_dev_register(const char *name, const struct rt_wlan_dev_ops *ops, rt_uint32_t flag, void *user_data)
 {
-    int i, ap_num;
-    struct rt_wlan_scan_result *_scan_result;
+    struct rt_wlan_device *wlan;
 
-    if (*scan_result != RT_NULL)
+    if (name == RT_NULL || ops == RT_NULL)
     {
-        _scan_result = *scan_result;
-        ap_num = _scan_result->ap_num;
-        for (i = 0; i < ap_num; i++)
-        {
-            if (_scan_result->ap_table[i].ssid != RT_NULL)
-            {
-                rt_free(_scan_result->ap_table[i].ssid);
-                _scan_result->ap_table[i].ssid = RT_NULL;
-            }
-        }
-        _scan_result->ap_num = 0;
-        rt_free(_scan_result->ap_table);
-        _scan_result->ap_table = RT_NULL;
+        LOG_E("F:%s L:%d parameter Wrongful", __FUNCTION__, __LINE__);
+        return RT_NULL;
     }
-    rt_free(*scan_result);
-    *scan_result = RT_NULL;
-    scan_result = RT_NULL;
+
+    wlan = rt_malloc(sizeof(struct rt_wlan_device));
+    if (wlan == RT_NULL)
+    {
+        LOG_E("F:%s L:%d", __FUNCTION__, __LINE__);
+        return RT_NULL;
+    }
+    rt_memset(wlan, 0, sizeof(struct rt_wlan_device));
+
+    wlan->device.init       = _rt_wlan_dev_init;
+    wlan->device.open       = RT_NULL;
+    wlan->device.close      = RT_NULL;
+    wlan->device.read       = RT_NULL;
+    wlan->device.write      = RT_NULL;
+    wlan->device.control    = _rt_wlan_dev_control;
+    wlan->device.user_data  = RT_NULL;
+
+    wlan->device.type = RT_Device_Class_NetIf;
+
+    wlan->ops = ops;
+    wlan->user_data  = user_data;
+
+    wlan->flags = flag;
+    rt_device_register(&wlan->device, name, RT_DEVICE_FLAG_RDWR);
+
+    LOG_D("F:%s L:%d run", __FUNCTION__, __LINE__);
+
+    return wlan;
 }

+ 508 - 143
components/drivers/wlan/wlan_dev.h

@@ -1,72 +1,66 @@
 /*
- *  RT-Thread Wi-Fi Device
+ * Copyright (c) 2006-2018, RT-Thread Development Team
  *
- * COPYRIGHT (C) 2014 - 2018, Shanghai Real-Thread Technology Co., Ltd
- *
- *  This file is part of RT-Thread (http://www.rt-thread.org)
- *
- *  All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * SPDX-License-Identifier: Apache-2.0
  *
  * Change Logs:
  * Date           Author       Notes
- * 2014-09-11     Bernard      the first verion
+ * 2018-08-03     tyx          the first version
  */
 
-#ifndef WIFI_DEVICE_H__
-#define WIFI_DEVICE_H__
+#ifndef __WLAN_DEVICE_H__
+#define __WLAN_DEVICE_H__
 
-#include <stdint.h>
-#include <netif/ethernetif.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 typedef enum
 {
-    WIFI_NONE,
-    WIFI_STATION,
-    WIFI_AP,
+    RT_WLAN_NONE,
+    RT_WLAN_STATION,
+    RT_WLAN_AP,
+    RT_WLAN_MODE_MAX
 } rt_wlan_mode_t;
 
 typedef enum
 {
-    WIFI_INIT = 0x10,
-    WIFI_SCAN,              /* trigger scanning (list cells) */
-    WIFI_JOIN,
-    WIFI_EASYJOIN,          /* join network with less information */
-    WIFI_SOFTAP,            /* start soft-AP */
-    WIFI_DISCONNECT,
-    WIFI_GET_RSSI,          /* get sensitivity (dBm) */
-    WIFI_ENTER_POWERSAVE,
-    WIFI_CFG_MONITOR,       /* start/stop minitor */
-    WIFI_SET_CHANNEL,
-    WIFI_GET_CHANNEL,
-    WIFI_SET_MONITOR_CALLBACK,
+    RT_WLAN_CMD_MODE = 0x10,
+    RT_WLAN_CMD_SCAN,              /* trigger scanning (list cells) */
+    RT_WLAN_CMD_JOIN,
+    RT_WLAN_CMD_SOFTAP,            /* start soft-AP */
+    RT_WLAN_CMD_DISCONNECT,
+    RT_WLAN_CMD_AP_STOP,           /* stop soft-AP */
+    RT_WLAN_CMD_AP_DEAUTH,
+    RT_WLAN_CMD_SCAN_STOP,
+    RT_WLAN_CMD_GET_RSSI,          /* get sensitivity (dBm) */
+    RT_WLAN_CMD_SET_POWERSAVE,
+    RT_WLAN_CMD_GET_POWERSAVE,
+    RT_WLAN_CMD_CFG_PROMISC,       /* start/stop minitor */
+    RT_WLAN_CMD_CFG_FILTER,
+    RT_WLAN_CMD_SET_CHANNEL,
+    RT_WLAN_CMD_GET_CHANNEL,
+    RT_WLAN_CMD_SET_COUNTRY,
+    RT_WLAN_CMD_GET_COUNTRY,
+    RT_WLAN_CMD_SET_MAC,
+    RT_WLAN_CMD_GET_MAC
 } rt_wlan_cmd_t;
 
 typedef enum
 {
-    WIFI_PWR_OFF,
-    WIFI_PWR_SLEEP,
-    WIFI_PWR_NORMAL
-} rt_wlan_powersave_t;
-
-typedef enum
-{
-    WIFI_MONITOR_START,
-    WIFI_MONITOR_STOP
-} rt_wlan_monitor_opition_t;
+    RT_WLAN_DEV_EVT_INIT_DONE = 0,
+    RT_WLAN_DEV_EVT_CONNECT,
+    RT_WLAN_DEV_EVT_CONNECT_FAIL,
+    RT_WLAN_DEV_EVT_DISCONNECT,
+    RT_WLAN_DEV_EVT_AP_START,
+    RT_WLAN_DEV_EVT_AP_STOP,
+    RT_WLAN_DEV_EVT_AP_ASSOCIATED,
+    RT_WLAN_DEV_EVT_AP_DISASSOCIATED,
+    RT_WLAN_DEV_EVT_AP_ASSOCIATE_FAILED,
+    RT_WLAN_DEV_EVT_SCAN_REPORT,
+    RT_WLAN_DEV_EVT_SCAN_DONE,
+    RT_WLAN_DEV_EVT_MAX,
+} rt_wlan_dev_event_t;
 
 #define SHARED_ENABLED  0x00008000
 #define WPA_SECURITY    0x00200000
@@ -77,144 +71,515 @@ typedef enum
 #define AES_ENABLED     0x0004
 #define WSEC_SWFLAG     0x0008
 
-#define KEY_ARRAY_SIZE  32
-#define SSID_LENGTH_MAX_SIZE  32 + 1
+#define RT_WLAN_FLAG_STA_ONLY    (0x1 << 0)
+#define RT_WLAN_FLAG_AP_ONLY     (0x1 << 1)
+
+#ifndef RT_WLAN_SSID_MAX_LENGTH
+#define RT_WLAN_SSID_MAX_LENGTH  (32)   /* SSID MAX LEN */
+#endif
+
+#ifndef RT_WLAN_BSSID_MAX_LENGTH
+#define RT_WLAN_BSSID_MAX_LENGTH (6)    /* BSSID MAX LEN (default is 6) */
+#endif
+
+#ifndef RT_WLAN_PASSWORD_MAX_LENGTH
+#define RT_WLAN_PASSWORD_MAX_LENGTH   (32)   /* PASSWORD MAX LEN*/
+#endif
+
+#ifndef RT_WLAN_DEV_EVENT_NUM
+#define RT_WLAN_DEV_EVENT_NUM  (2)   /* EVENT GROUP MAX NUM */
+#endif
+
 /**
  * Enumeration of Wi-Fi security modes
  */
 typedef enum
 {
-    SECURITY_OPEN           = 0,                                                /**< Open security                           */
-    SECURITY_WEP_PSK        = WEP_ENABLED,                                      /**< WEP Security with open authentication   */
-    SECURITY_WEP_SHARED     = (WEP_ENABLED | SHARED_ENABLED),                   /**< WEP Security with shared authentication */
-    SECURITY_WPA_TKIP_PSK   = (WPA_SECURITY  | TKIP_ENABLED),                   /**< WPA Security with TKIP                  */
-    SECURITY_WPA_AES_PSK    = (WPA_SECURITY  | AES_ENABLED),                    /**< WPA Security with AES                   */
-    SECURITY_WPA2_AES_PSK   = (WPA2_SECURITY | AES_ENABLED),                    /**< WPA2 Security with AES                  */
-    SECURITY_WPA2_TKIP_PSK  = (WPA2_SECURITY | TKIP_ENABLED),                   /**< WPA2 Security with TKIP                 */
-    SECURITY_WPA2_MIXED_PSK = (WPA2_SECURITY | AES_ENABLED | TKIP_ENABLED),     /**< WPA2 Security with AES & TKIP           */
-    SECURITY_WPS_OPEN       = WPS_ENABLED,                                      /**< WPS with open security                  */
-    SECURITY_WPS_SECURE     = (WPS_ENABLED | AES_ENABLED),                      /**< WPS with AES security                   */
-    SECURITY_UNKNOWN        = -1,                                               /**< May be returned by scan function if security is unknown.
-                                                                                     Do not pass this to the join function! */
+    SECURITY_OPEN           = 0,                                                /* Open security                           */
+    SECURITY_WEP_PSK        = WEP_ENABLED,                                      /* WEP Security with open authentication   */
+    SECURITY_WEP_SHARED     = (WEP_ENABLED | SHARED_ENABLED),                   /* WEP Security with shared authentication */
+    SECURITY_WPA_TKIP_PSK   = (WPA_SECURITY  | TKIP_ENABLED),                   /* WPA Security with TKIP                  */
+    SECURITY_WPA_AES_PSK    = (WPA_SECURITY  | AES_ENABLED),                    /* WPA Security with AES                   */
+    SECURITY_WPA2_AES_PSK   = (WPA2_SECURITY | AES_ENABLED),                    /* WPA2 Security with AES                  */
+    SECURITY_WPA2_TKIP_PSK  = (WPA2_SECURITY | TKIP_ENABLED),                   /* WPA2 Security with TKIP                 */
+    SECURITY_WPA2_MIXED_PSK = (WPA2_SECURITY | AES_ENABLED | TKIP_ENABLED),     /* WPA2 Security with AES & TKIP           */
+    SECURITY_WPS_OPEN       = WPS_ENABLED,                                      /* WPS with open security                  */
+    SECURITY_WPS_SECURE     = (WPS_ENABLED | AES_ENABLED),                      /* WPS with AES security                   */
+    SECURITY_UNKNOWN        = -1,                                               /* May be returned by scan function if security is unknown.
+                                                                                    Do not pass this to the join function! */
 } rt_wlan_security_t;
 
 typedef enum
 {
-    WIFI_EVT_INIT_DONE = 0,
-    WIFI_EVT_LINK_DOWN,
-    WIFI_EVT_LINK_UP,
-    WIFI_EVT_CONNECT,
-    WIFI_EVT_DISCONNECT,
-    WIFI_EVT_AP_START,
-    WIFI_EVT_AP_STOP,
-    WIFI_EVENT_STA_ASSOC,
-    WIFI_EVENT_STA_DISASSOC,
-    WIFI_EVT_SCAN_DONE,
-    WIFI_EVT_MAX,
-} rt_wlan_event_t;
-
-/* wifi network information */
-struct rt_wlan_info
+    RT_802_11_BAND_5GHZ  =  0,             /* Denotes 5GHz radio band   */
+    RT_802_11_BAND_2_4GHZ =  1,            /* Denotes 2.4GHz radio band */
+    RT_802_11_BAND_UNKNOWN = 0x7fffffff,   /* unknown */
+} rt_802_11_band_t;
+
+typedef enum
 {
-    rt_wlan_mode_t mode;   /* wifi mode */
-    rt_wlan_security_t security;
+    RT_COUNTRY_AFGHANISTAN,
+    RT_COUNTRY_ALBANIA,
+    RT_COUNTRY_ALGERIA,
+    RT_COUNTRY_AMERICAN_SAMOA,
+    RT_COUNTRY_ANGOLA,
+    RT_COUNTRY_ANGUILLA,
+    RT_COUNTRY_ANTIGUA_AND_BARBUDA,
+    RT_COUNTRY_ARGENTINA,
+    RT_COUNTRY_ARMENIA,
+    RT_COUNTRY_ARUBA,
+    RT_COUNTRY_AUSTRALIA,
+    RT_COUNTRY_AUSTRIA,
+    RT_COUNTRY_AZERBAIJAN,
+    RT_COUNTRY_BAHAMAS,
+    RT_COUNTRY_BAHRAIN,
+    RT_COUNTRY_BAKER_ISLAND,
+    RT_COUNTRY_BANGLADESH,
+    RT_COUNTRY_BARBADOS,
+    RT_COUNTRY_BELARUS,
+    RT_COUNTRY_BELGIUM,
+    RT_COUNTRY_BELIZE,
+    RT_COUNTRY_BENIN,
+    RT_COUNTRY_BERMUDA,
+    RT_COUNTRY_BHUTAN,
+    RT_COUNTRY_BOLIVIA,
+    RT_COUNTRY_BOSNIA_AND_HERZEGOVINA,
+    RT_COUNTRY_BOTSWANA,
+    RT_COUNTRY_BRAZIL,
+    RT_COUNTRY_BRITISH_INDIAN_OCEAN_TERRITORY,
+    RT_COUNTRY_BRUNEI_DARUSSALAM,
+    RT_COUNTRY_BULGARIA,
+    RT_COUNTRY_BURKINA_FASO,
+    RT_COUNTRY_BURUNDI,
+    RT_COUNTRY_CAMBODIA,
+    RT_COUNTRY_CAMEROON,
+    RT_COUNTRY_CANADA,
+    RT_COUNTRY_CAPE_VERDE,
+    RT_COUNTRY_CAYMAN_ISLANDS,
+    RT_COUNTRY_CENTRAL_AFRICAN_REPUBLIC,
+    RT_COUNTRY_CHAD,
+    RT_COUNTRY_CHILE,
+    RT_COUNTRY_CHINA,
+    RT_COUNTRY_CHRISTMAS_ISLAND,
+    RT_COUNTRY_COLOMBIA,
+    RT_COUNTRY_COMOROS,
+    RT_COUNTRY_CONGO,
+    RT_COUNTRY_CONGO_THE_DEMOCRATIC_REPUBLIC_OF_THE,
+    RT_COUNTRY_COSTA_RICA,
+    RT_COUNTRY_COTE_DIVOIRE,
+    RT_COUNTRY_CROATIA,
+    RT_COUNTRY_CUBA,
+    RT_COUNTRY_CYPRUS,
+    RT_COUNTRY_CZECH_REPUBLIC,
+    RT_COUNTRY_DENMARK,
+    RT_COUNTRY_DJIBOUTI,
+    RT_COUNTRY_DOMINICA,
+    RT_COUNTRY_DOMINICAN_REPUBLIC,
+    RT_COUNTRY_DOWN_UNDER,
+    RT_COUNTRY_ECUADOR,
+    RT_COUNTRY_EGYPT,
+    RT_COUNTRY_EL_SALVADOR,
+    RT_COUNTRY_EQUATORIAL_GUINEA,
+    RT_COUNTRY_ERITREA,
+    RT_COUNTRY_ESTONIA,
+    RT_COUNTRY_ETHIOPIA,
+    RT_COUNTRY_FALKLAND_ISLANDS_MALVINAS,
+    RT_COUNTRY_FAROE_ISLANDS,
+    RT_COUNTRY_FIJI,
+    RT_COUNTRY_FINLAND,
+    RT_COUNTRY_FRANCE,
+    RT_COUNTRY_FRENCH_GUINA,
+    RT_COUNTRY_FRENCH_POLYNESIA,
+    RT_COUNTRY_FRENCH_SOUTHERN_TERRITORIES,
+    RT_COUNTRY_GABON,
+    RT_COUNTRY_GAMBIA,
+    RT_COUNTRY_GEORGIA,
+    RT_COUNTRY_GERMANY,
+    RT_COUNTRY_GHANA,
+    RT_COUNTRY_GIBRALTAR,
+    RT_COUNTRY_GREECE,
+    RT_COUNTRY_GRENADA,
+    RT_COUNTRY_GUADELOUPE,
+    RT_COUNTRY_GUAM,
+    RT_COUNTRY_GUATEMALA,
+    RT_COUNTRY_GUERNSEY,
+    RT_COUNTRY_GUINEA,
+    RT_COUNTRY_GUINEA_BISSAU,
+    RT_COUNTRY_GUYANA,
+    RT_COUNTRY_HAITI,
+    RT_COUNTRY_HOLY_SEE_VATICAN_CITY_STATE,
+    RT_COUNTRY_HONDURAS,
+    RT_COUNTRY_HONG_KONG,
+    RT_COUNTRY_HUNGARY,
+    RT_COUNTRY_ICELAND,
+    RT_COUNTRY_INDIA,
+    RT_COUNTRY_INDONESIA,
+    RT_COUNTRY_IRAN_ISLAMIC_REPUBLIC_OF,
+    RT_COUNTRY_IRAQ,
+    RT_COUNTRY_IRELAND,
+    RT_COUNTRY_ISRAEL,
+    RT_COUNTRY_ITALY,
+    RT_COUNTRY_JAMAICA,
+    RT_COUNTRY_JAPAN,
+    RT_COUNTRY_JERSEY,
+    RT_COUNTRY_JORDAN,
+    RT_COUNTRY_KAZAKHSTAN,
+    RT_COUNTRY_KENYA,
+    RT_COUNTRY_KIRIBATI,
+    RT_COUNTRY_KOREA_REPUBLIC_OF,
+    RT_COUNTRY_KOSOVO,
+    RT_COUNTRY_KUWAIT,
+    RT_COUNTRY_KYRGYZSTAN,
+    RT_COUNTRY_LAO_PEOPLES_DEMOCRATIC_REPUBIC,
+    RT_COUNTRY_LATVIA,
+    RT_COUNTRY_LEBANON,
+    RT_COUNTRY_LESOTHO,
+    RT_COUNTRY_LIBERIA,
+    RT_COUNTRY_LIBYAN_ARAB_JAMAHIRIYA,
+    RT_COUNTRY_LIECHTENSTEIN,
+    RT_COUNTRY_LITHUANIA,
+    RT_COUNTRY_LUXEMBOURG,
+    RT_COUNTRY_MACAO,
+    RT_COUNTRY_MACEDONIA_FORMER_YUGOSLAV_REPUBLIC_OF,
+    RT_COUNTRY_MADAGASCAR,
+    RT_COUNTRY_MALAWI,
+    RT_COUNTRY_MALAYSIA,
+    RT_COUNTRY_MALDIVES,
+    RT_COUNTRY_MALI,
+    RT_COUNTRY_MALTA,
+    RT_COUNTRY_MAN_ISLE_OF,
+    RT_COUNTRY_MARTINIQUE,
+    RT_COUNTRY_MAURITANIA,
+    RT_COUNTRY_MAURITIUS,
+    RT_COUNTRY_MAYOTTE,
+    RT_COUNTRY_MEXICO,
+    RT_COUNTRY_MICRONESIA_FEDERATED_STATES_OF,
+    RT_COUNTRY_MOLDOVA_REPUBLIC_OF,
+    RT_COUNTRY_MONACO,
+    RT_COUNTRY_MONGOLIA,
+    RT_COUNTRY_MONTENEGRO,
+    RT_COUNTRY_MONTSERRAT,
+    RT_COUNTRY_MOROCCO,
+    RT_COUNTRY_MOZAMBIQUE,
+    RT_COUNTRY_MYANMAR,
+    RT_COUNTRY_NAMIBIA,
+    RT_COUNTRY_NAURU,
+    RT_COUNTRY_NEPAL,
+    RT_COUNTRY_NETHERLANDS,
+    RT_COUNTRY_NETHERLANDS_ANTILLES,
+    RT_COUNTRY_NEW_CALEDONIA,
+    RT_COUNTRY_NEW_ZEALAND,
+    RT_COUNTRY_NICARAGUA,
+    RT_COUNTRY_NIGER,
+    RT_COUNTRY_NIGERIA,
+    RT_COUNTRY_NORFOLK_ISLAND,
+    RT_COUNTRY_NORTHERN_MARIANA_ISLANDS,
+    RT_COUNTRY_NORWAY,
+    RT_COUNTRY_OMAN,
+    RT_COUNTRY_PAKISTAN,
+    RT_COUNTRY_PALAU,
+    RT_COUNTRY_PANAMA,
+    RT_COUNTRY_PAPUA_NEW_GUINEA,
+    RT_COUNTRY_PARAGUAY,
+    RT_COUNTRY_PERU,
+    RT_COUNTRY_PHILIPPINES,
+    RT_COUNTRY_POLAND,
+    RT_COUNTRY_PORTUGAL,
+    RT_COUNTRY_PUETO_RICO,
+    RT_COUNTRY_QATAR,
+    RT_COUNTRY_REUNION,
+    RT_COUNTRY_ROMANIA,
+    RT_COUNTRY_RUSSIAN_FEDERATION,
+    RT_COUNTRY_RWANDA,
+    RT_COUNTRY_SAINT_KITTS_AND_NEVIS,
+    RT_COUNTRY_SAINT_LUCIA,
+    RT_COUNTRY_SAINT_PIERRE_AND_MIQUELON,
+    RT_COUNTRY_SAINT_VINCENT_AND_THE_GRENADINES,
+    RT_COUNTRY_SAMOA,
+    RT_COUNTRY_SANIT_MARTIN_SINT_MARTEEN,
+    RT_COUNTRY_SAO_TOME_AND_PRINCIPE,
+    RT_COUNTRY_SAUDI_ARABIA,
+    RT_COUNTRY_SENEGAL,
+    RT_COUNTRY_SERBIA,
+    RT_COUNTRY_SEYCHELLES,
+    RT_COUNTRY_SIERRA_LEONE,
+    RT_COUNTRY_SINGAPORE,
+    RT_COUNTRY_SLOVAKIA,
+    RT_COUNTRY_SLOVENIA,
+    RT_COUNTRY_SOLOMON_ISLANDS,
+    RT_COUNTRY_SOMALIA,
+    RT_COUNTRY_SOUTH_AFRICA,
+    RT_COUNTRY_SPAIN,
+    RT_COUNTRY_SRI_LANKA,
+    RT_COUNTRY_SURINAME,
+    RT_COUNTRY_SWAZILAND,
+    RT_COUNTRY_SWEDEN,
+    RT_COUNTRY_SWITZERLAND,
+    RT_COUNTRY_SYRIAN_ARAB_REPUBLIC,
+    RT_COUNTRY_TAIWAN_PROVINCE_OF_CHINA,
+    RT_COUNTRY_TAJIKISTAN,
+    RT_COUNTRY_TANZANIA_UNITED_REPUBLIC_OF,
+    RT_COUNTRY_THAILAND,
+    RT_COUNTRY_TOGO,
+    RT_COUNTRY_TONGA,
+    RT_COUNTRY_TRINIDAD_AND_TOBAGO,
+    RT_COUNTRY_TUNISIA,
+    RT_COUNTRY_TURKEY,
+    RT_COUNTRY_TURKMENISTAN,
+    RT_COUNTRY_TURKS_AND_CAICOS_ISLANDS,
+    RT_COUNTRY_TUVALU,
+    RT_COUNTRY_UGANDA,
+    RT_COUNTRY_UKRAINE,
+    RT_COUNTRY_UNITED_ARAB_EMIRATES,
+    RT_COUNTRY_UNITED_KINGDOM,
+    RT_COUNTRY_UNITED_STATES,
+    RT_COUNTRY_UNITED_STATES_REV4,
+    RT_COUNTRY_UNITED_STATES_NO_DFS,
+    RT_COUNTRY_UNITED_STATES_MINOR_OUTLYING_ISLANDS,
+    RT_COUNTRY_URUGUAY,
+    RT_COUNTRY_UZBEKISTAN,
+    RT_COUNTRY_VANUATU,
+    RT_COUNTRY_VENEZUELA,
+    RT_COUNTRY_VIET_NAM,
+    RT_COUNTRY_VIRGIN_ISLANDS_BRITISH,
+    RT_COUNTRY_VIRGIN_ISLANDS_US,
+    RT_COUNTRY_WALLIS_AND_FUTUNA,
+    RT_COUNTRY_WEST_BANK,
+    RT_COUNTRY_WESTERN_SAHARA,
+    RT_COUNTRY_WORLD_WIDE_XX,
+    RT_COUNTRY_YEMEN,
+    RT_COUNTRY_ZAMBIA,
+    RT_COUNTRY_ZIMBABWE,
+    RT_COUNTRY_UNKNOWN
+} rt_country_code_t;
+
+struct rt_wlan_device;
+struct rt_wlan_buff;
+
+typedef void (*rt_wlan_dev_event_handler)(struct rt_wlan_device *device, rt_wlan_dev_event_t event, struct rt_wlan_buff *buff, void *parameter);
+
+typedef void (*rt_wlan_pormisc_callback_t)(struct rt_wlan_device *device, void *data, int len);
+
+struct rt_wlan_ssid
+{
+    rt_uint8_t len;
+    rt_uint8_t val[RT_WLAN_SSID_MAX_LENGTH + 1];
+};
+typedef struct rt_wlan_ssid rt_wlan_ssid_t;
+
+struct rt_wlan_key
+{
+    rt_uint8_t len;
+    rt_uint8_t val[RT_WLAN_PASSWORD_MAX_LENGTH + 1];
+};
+typedef struct rt_wlan_key rt_wlan_key_t;
 
-    char *ssid;
-    uint8_t bssid[6];
+#define INVALID_INFO(_info)       do {    \
+                                        rt_memset((_info), 0, sizeof(struct rt_wlan_info)); \
+                                        (_info)->band = RT_802_11_BAND_UNKNOWN; \
+                                        (_info)->security = SECURITY_UNKNOWN; \
+                                        (_info)->channel = -1; \
+                                    } while(0)
 
+struct rt_wlan_info
+{
+    /* security type */
+    rt_wlan_security_t security;
+    /* 2.4G/5G */
+    rt_802_11_band_t band;
     /* maximal data rate */
-    uint32_t datarate;
+    rt_uint32_t datarate;
     /* radio channel */
-    uint16_t channel;
+    rt_int16_t channel;
     /* signal strength */
-    int16_t  rssi;
+    rt_int16_t  rssi;
+    /* ssid */
+    rt_wlan_ssid_t ssid;
+    /* hwaddr */
+    rt_uint8_t bssid[RT_WLAN_BSSID_MAX_LENGTH];
+    rt_uint8_t hidden;
 };
 
-struct rt_wlan_info_request
+struct rt_wlan_buff
 {
-    uint16_t req_number;    /* the number of information item for request */
-    uint16_t rsp_number;    /* the number of information item for response */
+    void *data;
+    rt_int32_t len;
+};
 
-    struct rt_wlan_info *infos;/* the array of information to save response */
+struct rt_filter_pattern
+{
+    rt_uint16_t offset;     /* Offset in bytes to start filtering (referenced to the start of the ethernet packet) */
+    rt_uint16_t mask_size;  /* Size of the mask in bytes */
+    rt_uint8_t *mask;       /* Pattern mask bytes to be ANDed with the pattern eg. "\xff00" (must be in network byte order) */
+    rt_uint8_t *pattern;    /* Pattern bytes used to filter eg. "\x0800"  (must be in network byte order) */
 };
 
-typedef struct rt_wlan_scan_result
+typedef enum
 {
-    char ap_num;
-    struct rt_wlan_info *ap_table;
-} rt_wlan_scan_result_t;
+    RT_POSITIVE_MATCHING  = 0, /* Receive the data matching with this pattern and discard the other data  */
+    RT_NEGATIVE_MATCHING  = 1  /* Discard the data matching with this pattern and receive the other data */
+} rt_filter_rule_t;
 
-struct rt_wlan_device;
-typedef void (*rt_wlan_event_handler)(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data);
-typedef void (*rt_wlan_monitor_callback_t)(uint8_t *data, int len, void *user_data);
-struct rt_wlan_device
+struct rt_wlan_filter
 {
-    struct eth_device parent;
+    struct rt_filter_pattern patt;
+    rt_filter_rule_t rule;
+    rt_uint8_t enable;
+};
 
-    struct rt_wlan_info *info;
-    char key[KEY_ARRAY_SIZE + 1];
+struct rt_wlan_dev_event_desc
+{
+    rt_wlan_dev_event_handler handler;
+    void *parameter;
+};
 
-    rt_wlan_event_handler handler[WIFI_EVT_MAX];
+struct rt_wlan_device
+{
+    struct rt_device device;
+    rt_wlan_mode_t mode;
+    struct rt_mutex lock;
+    struct rt_wlan_dev_event_desc handler_table[RT_WLAN_DEV_EVT_MAX][RT_WLAN_DEV_EVENT_NUM];
+    rt_wlan_pormisc_callback_t pormisc_callback;
+    const struct rt_wlan_dev_ops *ops;
+    rt_uint32_t flags;
+    void *prot;
     void *user_data;
-    int interface;
+};
+
+struct rt_sta_info
+{
+    rt_wlan_ssid_t ssid;
+    rt_wlan_key_t key;
+    rt_uint8_t bssid[6];
+    rt_uint16_t channel;
+    rt_wlan_security_t security;
+};
+
+struct rt_ap_info
+{
+    rt_wlan_ssid_t ssid;
+    rt_wlan_key_t key;
+    rt_bool_t hidden;
+    rt_uint16_t channel;
+    rt_wlan_security_t security;
+};
+
+struct rt_scan_info
+{
+    rt_wlan_ssid_t ssid;
+    rt_uint8_t bssid[6];
+    rt_int16_t channel_min;
+    rt_int16_t channel_max;
+};
+
+struct rt_wlan_dev_ops
+{
+    rt_err_t (*wlan_init)(struct rt_wlan_device *wlan);
+    rt_err_t (*wlan_mode)(struct rt_wlan_device *wlan, rt_wlan_mode_t mode);
+    rt_err_t (*wlan_scan)(struct rt_wlan_device *wlan, struct rt_scan_info *scan_info);
+    rt_err_t (*wlan_join)(struct rt_wlan_device *wlan, struct rt_sta_info *sta_info);
+    rt_err_t (*wlan_softap)(struct rt_wlan_device *wlan, struct rt_ap_info *ap_info);
+    rt_err_t (*wlan_disconnect)(struct rt_wlan_device *wlan);
+    rt_err_t (*wlan_ap_stop)(struct rt_wlan_device *wlan);
+    rt_err_t (*wlan_ap_deauth)(struct rt_wlan_device *wlan, rt_uint8_t mac[]);
+    rt_err_t (*wlan_scan_stop)(struct rt_wlan_device *wlan);
+    int (*wlan_get_rssi)(struct rt_wlan_device *wlan);
+    rt_err_t (*wlan_set_powersave)(struct rt_wlan_device *wlan, int level);
+    int (*wlan_get_powersave)(struct rt_wlan_device *wlan);
+    rt_err_t (*wlan_cfg_promisc)(struct rt_wlan_device *wlan, rt_bool_t start);
+    rt_err_t (*wlan_cfg_filter)(struct rt_wlan_device *wlan, struct rt_wlan_filter *filter);
+    rt_err_t (*wlan_set_channel)(struct rt_wlan_device *wlan, int channel);
+    int (*wlan_get_channel)(struct rt_wlan_device *wlan);
+    rt_err_t (*wlan_set_country)(struct rt_wlan_device *wlan, rt_country_code_t country_code);
+    rt_country_code_t (*wlan_get_country)(struct rt_wlan_device *wlan);
+    rt_err_t (*wlan_set_mac)(struct rt_wlan_device *wlan, rt_uint8_t mac[]);
+    rt_err_t (*wlan_get_mac)(struct rt_wlan_device *wlan, rt_uint8_t mac[]);
+    int (*wlan_recv)(struct rt_wlan_device *wlan, void *buff, int len);
+    int (*wlan_send)(struct rt_wlan_device *wlan, void *buff, int len);
 };
 
 /*
- * Wi-Fi Information APIs
+ * wlan device init
  */
-void rt_wlan_info_init(struct rt_wlan_info *info, rt_wlan_mode_t mode, rt_wlan_security_t security,
-                       char *ssid);
-void rt_wlan_info_deinit(struct rt_wlan_info *info);
+rt_err_t rt_wlan_dev_init(struct rt_wlan_device *device, rt_wlan_mode_t mode);
 
 /*
- * Wi-Fi Manager APIs
+ * wlan device station interface
  */
-int rt_wlan_init(struct rt_wlan_device *device, rt_wlan_mode_t mode);
-
-int rt_wlan_connect(struct rt_wlan_device *device, struct rt_wlan_info *info,
-                    char *password);
-int rt_wlan_disconnect(struct rt_wlan_device *device);
+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_disconnect(struct rt_wlan_device *device);
+int rt_wlan_dev_get_rssi(struct rt_wlan_device *device);
 
-int rt_wlan_softap(struct rt_wlan_device *device, struct rt_wlan_info *info,
-                   char *password);
+/*
+ * wlan device ap interface
+ */
+rt_err_t rt_wlan_dev_ap_start(struct rt_wlan_device *device, struct rt_wlan_info *info, const char *password, int password_len);
+rt_err_t rt_wlan_dev_ap_stop(struct rt_wlan_device *device);
+rt_err_t rt_wlan_dev_ap_deauth(struct rt_wlan_device *device, rt_uint8_t mac[6]);
 
-/* set wifi information for AP */
-int rt_wlan_set_info(struct rt_wlan_device *device, struct rt_wlan_info *info);
-/* get wifi information for AP */
-struct rt_wlan_info *rt_wlan_get_info(struct rt_wlan_device *device);
+/*
+ * wlan device scan interface
+ */
+rt_err_t rt_wlan_dev_scan(struct rt_wlan_device *device, struct rt_wlan_info *info);
+rt_err_t rt_wlan_dev_scan_stop(struct rt_wlan_device *device);
 
-/* get the AP result which were scaned in station */
-int rt_wlan_scan(struct rt_wlan_device *device, struct rt_wlan_scan_result **scan_result);
+/*
+ * wlan device mac interface
+ */
+rt_err_t rt_wlan_dev_get_mac(struct rt_wlan_device *device, rt_uint8_t mac[6]);
+rt_err_t rt_wlan_dev_set_mac(struct rt_wlan_device *device, rt_uint8_t mac[6]);
 
-/* get rssi */
-int rt_wlan_get_rssi(struct rt_wlan_device *device);
-/* Get/Set MAC */
-int rt_wlan_get_mac(struct rt_wlan_device *device, rt_uint8_t hwaddr[6]);
-int rt_wlan_set_mac(struct rt_wlan_device *device, rt_uint8_t hwaddr[6]);
+/*
+ * wlan device powersave interface
+ */
+rt_err_t rt_wlan_dev_set_powersave(struct rt_wlan_device *device, int level);
+int rt_wlan_dev_get_powersave(struct rt_wlan_device *device);
 
-/* enter power save level */
-int rt_wlan_enter_powersave(struct rt_wlan_device *device, int level);
+/*
+ * wlan device event interface
+ */
+rt_err_t rt_wlan_dev_register_event_handler(struct rt_wlan_device *device, rt_wlan_dev_event_t event, rt_wlan_dev_event_handler handler, void *parameter);
+rt_err_t rt_wlan_dev_unregister_event_handler(struct rt_wlan_device *device, rt_wlan_dev_event_t event, rt_wlan_dev_event_handler handler);
+void rt_wlan_dev_indicate_event_handle(struct rt_wlan_device *device, rt_wlan_dev_event_t event, struct rt_wlan_buff *buff);
 
-/* register the event handler */
-int rt_wlan_register_event_handler(struct rt_wlan_device *device, rt_wlan_event_t event,
-                                   rt_wlan_event_handler handler);
+/*
+ * wlan device promisc interface
+ */
+rt_err_t rt_wlan_dev_enter_promisc(struct rt_wlan_device *device);
+rt_err_t rt_wlan_dev_exit_promisc(struct rt_wlan_device *device);
+rt_err_t rt_wlan_dev_set_promisc_callback(struct rt_wlan_device *device, rt_wlan_pormisc_callback_t callback);
+void rt_wlan_dev_promisc_handler(struct rt_wlan_device *device, void *data, int len);
 
-/* un-register the event handler */
-int rt_wlan_unregister_event_handler(struct rt_wlan_device *device, rt_wlan_event_t event);
+/*
+ * wlan device filter interface
+ */
+rt_err_t rt_wlan_dev_cfg_filter(struct rt_wlan_device *device, struct rt_wlan_filter *filter);
 
-/* wlan driver indicate event to upper layer through wifi_indication. */
-int rt_wlan_indicate_event_handle(struct rt_wlan_device *device, rt_wlan_event_t event,
-                                  void *user_data);
+/*
+ * wlan device channel interface
+ */
+rt_err_t rt_wlan_dev_set_channel(struct rt_wlan_device *device, int channel);
+rt_err_t rt_wlan_dev_get_channel(struct rt_wlan_device *device);
 
-/* start or stop monitor */
-int rt_wlan_cfg_monitor(struct rt_wlan_device *device, rt_wlan_monitor_opition_t opition);
+/*
+ * wlan device country interface
+ */
+rt_err_t rt_wlan_dev_set_country(struct rt_wlan_device *device, rt_country_code_t country_code);
+rt_country_code_t rt_wlan_dev_get_country(struct rt_wlan_device *device);
 
-/* set callback function for monitor mode*/
-int rt_wlan_set_monitor_callback(struct rt_wlan_device *device, rt_wlan_monitor_callback_t callback);
+/*
+ * wlan device datat transfer interface
+ */
+rt_err_t rt_wlan_dev_report_data(struct rt_wlan_device *device, void *buff, int len);
+// void rt_wlan_dev_data_ready(struct rt_wlan_device *device, int len);
 
-/* Set the monitor channel */
-int rt_wlan_set_channel(struct rt_wlan_device *device, int channel);
+/*
+ * wlan device register interface
+ */
+struct rt_wlan_device *rt_wlan_dev_register(const char *name, const struct rt_wlan_dev_ops *ops, rt_uint32_t flag, void *user_data);
 
-void rt_wlan_release_scan_result(struct rt_wlan_scan_result **scan_result);
+#ifdef __cplusplus
+}
+#endif
 
 #endif

+ 483 - 0
components/drivers/wlan/wlan_lwip.c

@@ -0,0 +1,483 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-14     tyx          the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <wlan_dev.h>
+#include <wlan_prot.h>
+#include <wlan_workqueue.h>
+
+#ifdef RT_USING_LWIP
+#include <netif/ethernetif.h>
+#include <lwip/netifapi.h>
+#ifdef LWIP_USING_DHCPD
+#include <dhcp_server.h>
+#endif
+
+#define DBG_ENABLE
+#ifdef RT_WLAN_LWIP_DEBUG
+#define DBG_LEVEL DBG_LOG
+#else
+#define DBG_LEVEL DBG_INFO
+#endif
+#define DBG_SECTION_NAME  "WLAN.lwip"
+#define DBG_COLOR
+#include <rtdbg.h>
+
+struct lwip_prot_des
+{
+    struct rt_wlan_prot prot;
+    struct eth_device eth;
+    rt_int8_t connected_flag;
+    struct rt_timer timer;
+    struct rt_work work;
+};
+
+static void netif_is_ready(struct rt_work *work, void *parameter)
+{
+    ip_addr_t ip_addr_zero = { 0 };
+    struct rt_wlan_device *wlan = parameter;
+    struct lwip_prot_des *lwip_prot = (struct lwip_prot_des *)wlan->prot;
+    struct eth_device *eth_dev = &lwip_prot->eth;
+    char str[IP4ADDR_STRLEN_MAX];
+    rt_base_t level;
+    struct rt_wlan_buff buff;
+    rt_uint32_t ip_addr[4];
+
+    rt_timer_stop(&lwip_prot->timer);
+    if (ip_addr_cmp(&(eth_dev->netif->ip_addr), &ip_addr_zero) != 0)
+    {
+        rt_timer_start(&lwip_prot->timer);
+        goto exit;
+    }
+    rt_memset(&ip_addr, 0, sizeof(ip_addr));
+#if LWIP_IPV4 && LWIP_IPV6
+    if (eth_dev->netif->ip_addr.type == IPADDR_TYPE_V4)
+    {
+        ip_addr[0] = ip4_addr_get_u32(&eth_dev->netif->ip_addr.u_addr.ip4);
+        buff.data = &ip_addr[0];
+        buff.len = sizeof(ip_addr[0]);
+    }
+    else if (eth_dev->netif->ip_addr.type == IPADDR_TYPE_V6)
+    {
+        *(ip6_addr_t *)(&ip_addr[0]) = eth_dev->netif->ip_addr.u_addr.ip6;
+        buff.data = ip_addr;
+        buff.len = sizeof(ip_addr);
+    }
+    else
+    {
+        LOG_W("F:%s L:%d ip addr type not support", __FUNCTION__, __LINE__);
+    }
+#else
+#if LWIP_IPV4
+    ip_addr[0] = ip4_addr_get_u32(&eth_dev->netif->ip_addr);
+    buff.data = &ip_addr[0];
+    buff.len = sizeof(ip_addr[0]);
+#else
+    *(ip_addr_t *)(&ip_addr[0]) = eth_dev->netif->ip_addr;
+    buff.data = ip_addr;
+    buff.len = sizeof(ip_addr);
+#endif
+#endif
+    if (rt_wlan_prot_ready(wlan, &buff) != 0)
+    {
+        rt_timer_start(&lwip_prot->timer);
+        goto exit;
+    }
+    rt_memset(str, 0, IP4ADDR_STRLEN_MAX);
+    rt_enter_critical();
+    rt_memcpy(str, ipaddr_ntoa(&(eth_dev->netif->ip_addr)), IP4ADDR_STRLEN_MAX);
+    rt_exit_critical();
+    LOG_I("Got IP address : %s", str);
+exit:
+    level = rt_hw_interrupt_disable();
+    rt_memset(work, 0, sizeof(struct rt_work));
+    rt_hw_interrupt_enable(level);
+}
+
+static void timer_callback(void *parameter)
+{
+    struct rt_workqueue *workqueue;
+    struct rt_wlan_device *wlan = parameter;
+    struct lwip_prot_des *lwip_prot = (struct lwip_prot_des *)wlan->prot;
+    struct rt_work *work = &lwip_prot->work;
+    rt_base_t level;
+
+    workqueue = rt_wlan_get_workqueue();
+    if (workqueue != RT_NULL)
+    {
+        level = rt_hw_interrupt_disable();
+        rt_work_init(work, netif_is_ready, parameter);
+        rt_hw_interrupt_enable(level);
+        if (rt_workqueue_dowork(workqueue, work) != RT_EOK)
+        {
+            level = rt_hw_interrupt_disable();
+            rt_memset(work, 0, sizeof(struct rt_work));
+            rt_hw_interrupt_enable(level);
+        }
+    }
+}
+
+static void netif_set_connected(void *parameter)
+{
+    struct rt_wlan_device *wlan = parameter;
+    struct lwip_prot_des *lwip_prot = wlan->prot;
+    struct eth_device *eth_dev = &lwip_prot->eth;
+
+    if (lwip_prot->connected_flag)
+    {
+        if (wlan->mode == RT_WLAN_STATION)
+        {
+            LOG_D("F:%s L:%d dhcp start run", __FUNCTION__, __LINE__);
+            netifapi_netif_set_link_up(eth_dev->netif);
+#ifdef RT_LWIP_DHCP
+            dhcp_start(eth_dev->netif);
+#endif
+            rt_timer_start(&lwip_prot->timer);
+        }
+        else if (wlan->mode == RT_WLAN_AP)
+        {
+            LOG_D("F:%s L:%d dhcpd start run", __FUNCTION__, __LINE__);
+
+            netifapi_netif_set_link_up(eth_dev->netif);
+#ifdef LWIP_USING_DHCPD
+            {
+                char netif_name[8];
+                int i;
+
+                rt_memset(netif_name, 0, sizeof(netif_name));
+                for (i = 0; i < sizeof(eth_dev->netif->name); i++)
+                {
+                    netif_name[i] = eth_dev->netif->name[i];
+                }
+                dhcpd_start(netif_name);
+            }
+#endif
+        }
+    }
+    else
+    {
+        if (wlan->mode == RT_WLAN_STATION)
+        {
+            LOG_D("F:%s L:%d dhcp stop run", __FUNCTION__, __LINE__);
+            netifapi_netif_set_link_down(eth_dev->netif);
+#ifdef RT_LWIP_DHCP
+            {
+                ip4_addr_t ip_addr = { 0 };
+                dhcp_stop(eth_dev->netif);
+                netif_set_addr(eth_dev->netif, &ip_addr, &ip_addr, &ip_addr);
+            }
+#endif
+            rt_timer_stop(&lwip_prot->timer);
+        }
+        else if (wlan->mode == RT_WLAN_AP)
+        {
+            LOG_D("F:%s L:%d dhcpd stop run", __FUNCTION__, __LINE__);
+            netifapi_netif_set_link_down(eth_dev->netif);
+        }
+    }
+}
+
+static void rt_wlan_lwip_event_handle(struct rt_wlan_prot *port, struct rt_wlan_device *wlan, int event)
+{
+    struct lwip_prot_des *lwip_prot = (struct lwip_prot_des *)wlan->prot;
+    rt_bool_t flag_old;
+
+    flag_old = lwip_prot->connected_flag;
+
+    switch (event)
+    {
+    case RT_WLAN_PROT_EVT_CONNECT:
+    {
+        LOG_D("event: CONNECT");
+        lwip_prot->connected_flag = RT_TRUE;
+        break;
+    }
+    case RT_WLAN_PROT_EVT_DISCONNECT:
+    {
+        LOG_D("event: DISCONNECT");
+        lwip_prot->connected_flag = RT_FALSE;
+        break;
+    }
+    case RT_WLAN_PROT_EVT_AP_START:
+    {
+        LOG_D("event: AP_START");
+        lwip_prot->connected_flag = RT_TRUE;
+        break;
+    }
+    case RT_WLAN_PROT_EVT_AP_STOP:
+    {
+        LOG_D("event: AP_STOP");
+        lwip_prot->connected_flag = RT_FALSE;
+        break;
+    }
+    case RT_WLAN_PROT_EVT_AP_ASSOCIATED:
+    {
+        LOG_D("event: ASSOCIATED");
+        break;
+    }
+    case RT_WLAN_PROT_EVT_AP_DISASSOCIATED:
+    {
+        LOG_D("event: DISASSOCIATED");
+        break;
+    }
+    default :
+    {
+        LOG_D("event: UNKNOWN");
+        break;
+    }
+    }
+    if (flag_old != lwip_prot->connected_flag)
+    {
+        rt_wlan_workqueue_dowork(netif_set_connected, wlan);
+        // netif_set_connected(wlan);
+    }
+}
+
+static rt_err_t rt_wlan_lwip_protocol_control(rt_device_t device, int cmd, void *args)
+{
+    struct eth_device *eth_dev = (struct eth_device *)device;
+    struct rt_wlan_device *wlan;
+    rt_err_t err = RT_EOK;
+
+    RT_ASSERT(eth_dev != RT_NULL);
+
+    LOG_D("F:%s L:%d device:0x%08x user_data:0x%08x", __FUNCTION__, __LINE__, eth_dev, eth_dev->parent.user_data);
+
+    switch (cmd)
+    {
+    case NIOCTL_GADDR:
+        /* get MAC address */
+        wlan = eth_dev->parent.user_data;
+        err = rt_device_control((rt_device_t)wlan, RT_WLAN_CMD_GET_MAC, args);
+        break;
+    default :
+        break;
+    }
+    return err;
+}
+
+static rt_err_t rt_wlan_lwip_protocol_recv(struct rt_wlan_device *wlan, void *buff, int len)
+{
+    struct eth_device *eth_dev = &((struct lwip_prot_des *)wlan->prot)->eth;
+    struct pbuf *p = RT_NULL;
+
+    LOG_D("F:%s L:%d run", __FUNCTION__, __LINE__);
+
+    if (eth_dev == RT_NULL)
+    {
+        return -RT_ERROR;
+    }
+#ifdef RT_WLAN_PROT_LWIP_PBUF_FORCE
+    {
+        p = buff;
+        if ((eth_dev->netif->input(p, eth_dev->netif)) != ERR_OK)
+        {
+            return -RT_ERROR;
+        }
+        return RT_EOK;
+    }
+#else
+    {
+        int count = 0;
+
+        while (p == RT_NULL)
+        {
+            p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
+            if (p != RT_NULL)
+                break;
+
+            p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM);
+            if (p != RT_NULL)
+                break;
+
+            LOG_D("F:%s L:%d wait for pbuf_alloc!", __FUNCTION__, __LINE__);
+            rt_thread_delay(1);
+            count++;
+
+            //wait for 10ms or give up!!
+            if (count >= 10)
+            {
+                LOG_W("F:%s L:%d pbuf allocate fail!!!", __FUNCTION__, __LINE__);
+                return -RT_ENOMEM;
+            }
+        }
+        /*copy data dat -> pbuf*/
+        pbuf_take(p, buff, len);
+        if ((eth_dev->netif->input(p, eth_dev->netif)) != ERR_OK)
+        {
+            LOG_D("F:%s L:%d IP input error", __FUNCTION__, __LINE__);
+            pbuf_free(p);
+            p = RT_NULL;
+        }
+        LOG_D("F:%s L:%d netif iput success! len:%d", __FUNCTION__, __LINE__, len);
+        return RT_EOK;
+    }
+#endif
+}
+
+static rt_err_t rt_wlan_lwip_protocol_send(rt_device_t device, struct pbuf *p)
+{
+    struct rt_wlan_device *wlan = ((struct eth_device *)device)->parent.user_data;
+
+    LOG_D("F:%s L:%d run", __FUNCTION__, __LINE__);
+
+    if (wlan == RT_NULL)
+    {
+        return RT_EOK;
+    }
+
+#ifdef RT_WLAN_PROT_LWIP_PBUF_FORCE
+    {
+        rt_wlan_prot_transfer_dev(wlan, p, p->tot_len);
+        return RT_EOK;
+    }
+#else
+    {
+        rt_uint8_t *frame;
+
+        /* sending data directly */
+        if (p->len == p->tot_len)
+        {
+            frame = (rt_uint8_t *)p->payload;
+            rt_wlan_prot_transfer_dev(wlan, frame, p->tot_len);
+            LOG_D("F:%s L:%d run len:%d", __FUNCTION__, __LINE__, p->tot_len);
+            return RT_EOK;
+        }
+        frame = rt_malloc(p->tot_len);
+        if (frame == RT_NULL)
+        {
+            LOG_E("F:%s L:%d malloc out_buf fail\n", __FUNCTION__, __LINE__);
+            return -RT_ENOMEM;
+        }
+        /*copy pbuf -> data dat*/
+        pbuf_copy_partial(p, frame, p->tot_len, 0);
+        /* send data */
+        rt_wlan_prot_transfer_dev(wlan, frame, p->tot_len);
+        LOG_D("F:%s L:%d run len:%d", __FUNCTION__, __LINE__, p->tot_len);
+        rt_free(frame);
+        return RT_EOK;
+    }
+#endif
+}
+
+static struct rt_wlan_prot *rt_wlan_lwip_protocol_register(struct rt_wlan_prot *prot, struct rt_wlan_device *wlan)
+{
+    struct eth_device *eth = RT_NULL;
+    static rt_uint8_t id = 0;
+    char eth_name[4], timer_name[16];
+    rt_device_t device = RT_NULL;
+    struct lwip_prot_des *lwip_prot;
+
+    if (wlan == RT_NULL || prot == RT_NULL)
+        return RT_NULL;;
+
+    LOG_D("F:%s L:%d is run wlan:0x%08x", __FUNCTION__, __LINE__, wlan);
+
+    do
+    {
+        /* find ETH device name */
+        eth_name[0] = 'w';
+        eth_name[1] = '0' + id++;
+        eth_name[2] = '\0';
+        device = rt_device_find(eth_name);
+    }
+    while (device);
+
+    if (id > 9)
+    {
+        LOG_E("F:%s L:%d not find Empty name", __FUNCTION__, __LINE__, eth_name);
+        return RT_NULL;
+    }
+
+    if (rt_device_open((rt_device_t)wlan, RT_DEVICE_OFLAG_RDWR) != RT_EOK)
+    {
+        LOG_E("F:%s L:%d open wlan failed", __FUNCTION__, __LINE__);
+        return RT_NULL;
+    }
+
+    lwip_prot = rt_malloc(sizeof(struct lwip_prot_des));
+    if (lwip_prot == RT_NULL)
+    {
+        LOG_E("F:%s L:%d malloc mem failed", __FUNCTION__, __LINE__);
+        rt_device_close((rt_device_t)wlan);
+        return RT_NULL;
+    }
+    rt_memset(lwip_prot, 0, sizeof(struct lwip_prot_des));
+
+    eth = &lwip_prot->eth;
+    eth->parent.init       = RT_NULL;
+    eth->parent.open       = RT_NULL;
+    eth->parent.close      = RT_NULL;
+    eth->parent.read       = RT_NULL;
+    eth->parent.write      = RT_NULL;
+    eth->parent.control    = rt_wlan_lwip_protocol_control;
+    eth->parent.user_data  = wlan;
+    eth->eth_rx     = RT_NULL;
+    eth->eth_tx     = rt_wlan_lwip_protocol_send;
+
+    /* register ETH device */
+    if (eth_device_init(eth, eth_name) != RT_EOK)
+    {
+        LOG_E("eth device init failed");
+        rt_device_close((rt_device_t)wlan);
+        rt_free(lwip_prot);
+        return RT_NULL;
+    }
+    rt_memcpy(&lwip_prot->prot, prot, sizeof(struct rt_wlan_prot));
+    if (wlan->mode == RT_WLAN_STATION)
+    {
+        rt_sprintf(timer_name, "timer_%s", eth_name);
+        rt_timer_init(&lwip_prot->timer, timer_name, timer_callback, wlan, rt_tick_from_millisecond(1000),
+                      RT_TIMER_FLAG_SOFT_TIMER | RT_TIMER_FLAG_ONE_SHOT);
+    }
+    LOG_I("eth device init ok name:%s", eth_name);
+
+    return &lwip_prot->prot;
+}
+
+static void rt_wlan_lwip_protocol_unregister(struct rt_wlan_prot *prot, struct rt_wlan_device *wlan)
+{
+    /*TODO*/
+    LOG_D("F:%s L:%d is run wlan:0x%08x", __FUNCTION__, __LINE__, wlan);
+}
+
+static struct rt_wlan_prot_ops ops =
+{
+    rt_wlan_lwip_protocol_recv,
+    rt_wlan_lwip_protocol_register,
+    rt_wlan_lwip_protocol_unregister
+};
+
+int rt_wlan_lwip_init(void)
+{
+    static struct rt_wlan_prot prot;
+    rt_wlan_prot_event_t event;
+
+    rt_memset(&prot, 0, sizeof(prot));
+    rt_strncpy(&prot.name[0], RT_WLAN_PROT_LWIP, RT_WLAN_PROT_NAME_LEN);
+    prot.ops = &ops;
+
+    if (rt_wlan_prot_regisetr(&prot) != RT_EOK)
+    {
+        LOG_E("F:%s L:%d protocol regisetr failed", __FUNCTION__, __LINE__);
+        return -1;
+    }
+
+    for (event = RT_WLAN_PROT_EVT_INIT_DONE; event < RT_WLAN_PROT_EVT_MAX; event++)
+    {
+        rt_wlan_prot_event_register(&prot, event, rt_wlan_lwip_event_handle);
+    }
+
+    return 0;
+}
+INIT_PREV_EXPORT(rt_wlan_lwip_init);
+
+#endif

+ 1826 - 86
components/drivers/wlan/wlan_mgnt.c

@@ -1,142 +1,1882 @@
 /*
- *  RT-Thread Wi-Fi Device
+ * Copyright (c) 2006-2018, RT-Thread Development Team
  *
- * COPYRIGHT (C) 2014 - 2018, Shanghai Real-Thread Technology Co., Ltd
- *
- *  This file is part of RT-Thread (http://www.rt-thread.org)
- *
- *  All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * SPDX-License-Identifier: Apache-2.0
  *
  * Change Logs:
  * Date           Author       Notes
- * 2018-02-27     EvalZero     the first verion
+ * 2018-08-06     tyx          the first version
  */
 
+#include <rthw.h>
 #include <rtthread.h>
-#include <rtdevice.h>
+#include <wlan_dev.h>
+#include <wlan_cfg.h>
+#include <wlan_mgnt.h>
+#include <wlan_prot.h>
+#include <wlan_workqueue.h>
 
-#include <lwip/netifapi.h>
-
-#include "wlan_dev.h"
-#include "wlan_cmd.h"
-
-#define WLAN_MGNT_DEBUG   1
-
-#if WLAN_MGNT_DEBUG
-#define WLAN_MGNT_DBG(...)     rt_kprintf("[WLAN_MGNT]"),rt_kprintf(__VA_ARGS__)
+#define DBG_ENABLE
+#ifdef RT_WLAN_MGNT_DEBUG
+#define DBG_LEVEL DBG_LOG
 #else
-#define WLAN_MGNT_DBG(...)
+#define DBG_LEVEL DBG_INFO
 #endif
+#define DBG_SECTION_NAME  "WLAN.mgnt"
+#define DBG_COLOR
+#include <rtdbg.h>
 
-#ifndef WIFI_DEVICE_STA_NAME
-#define WIFI_DEVICE_STA_NAME    "w0"
+#ifndef RT_WLAN_DEVICE
+#define RT_WLAN_DEVICE(__device) ((struct rt_wlan_device *)__device)
 #endif
-#ifndef WIFI_DEVICE_AP_NAME
-#define WIFI_DEVICE_AP_NAME    "ap"
+
+#define RT_WLAN_LOG_D(_fmt, ...) LOG_D("L:%d "_fmt"", __LINE__, ##__VA_ARGS__)
+#define RT_WLAN_LOG_I(...) LOG_I(__VA_ARGS__)
+#define RT_WLAN_LOG_W(_fmt, ...) LOG_W("F:%s L:%d "_fmt"", __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define RT_WLAN_LOG_E(_fmt, ...) LOG_E("F:%s L:%d "_fmt"", __FUNCTION__, __LINE__, ##__VA_ARGS__)
+
+#define STA_DEVICE()  (_sta_mgnt.device)
+#define AP_DEVICE()  (_ap_mgnt.device)
+
+#define SRESULT_LOCK()    (rt_mutex_take(&scan_result_mutex, RT_WAITING_FOREVER))
+#define SRESULT_UNLOCK()  (rt_mutex_release(&scan_result_mutex))
+
+#define STAINFO_LOCK()    (rt_mutex_take(&sta_info_mutex, RT_WAITING_FOREVER))
+#define STAINFO_UNLOCK()  (rt_mutex_release(&sta_info_mutex))
+
+#define MGNT_LOCK()       (rt_mutex_take(&mgnt_mutex, RT_WAITING_FOREVER))
+#define MGNT_UNLOCK()     (rt_mutex_release(&mgnt_mutex))
+
+#define COMPLETE_LOCK()       (rt_mutex_take(&complete_mutex, RT_WAITING_FOREVER))
+#define COMPLETE_UNLOCK()     (rt_mutex_release(&complete_mutex))
+
+#define TIME_STOP()    (rt_timer_stop(&reconnect_time))
+#define TIME_START()   (rt_timer_start(&reconnect_time))
+
+#define DISCONNECT_RESPONSE_TICK    (2000)
+
+#if RT_WLAN_EBOX_NUM < 1
+#error "event box num Too little"
 #endif
 
-static void wlan_mgnt_init_done_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data)
+struct rt_wlan_mgnt_des
+{
+    struct rt_wlan_device *device;
+    struct rt_wlan_info info;
+    struct rt_wlan_key key;
+    rt_uint8_t state;
+    rt_uint8_t flags;
+};
+
+struct rt_wlan_event_desc
+{
+    rt_wlan_event_handler handler;
+    void *parameter;
+};
+
+struct rt_wlan_sta_list
+{
+    struct rt_wlan_sta_list *next;
+    struct rt_wlan_info info;
+};
+
+struct rt_wlan_sta_des
+{
+    int num;
+    struct rt_wlan_sta_list *node;
+};
+
+struct rt_wlan_msg
+{
+    rt_int32_t event;
+    rt_int32_t len;
+    void *buff;
+};
+
+struct rt_wlan_complete_des
+{
+    struct rt_event complete;
+    rt_uint32_t event_flag;
+    int index;
+};
+
+static struct rt_mutex mgnt_mutex;
+
+static struct rt_wlan_mgnt_des _sta_mgnt;
+static struct rt_wlan_mgnt_des _ap_mgnt;
+
+static struct rt_wlan_scan_result scan_result;
+static struct rt_mutex scan_result_mutex;
+
+static struct rt_wlan_sta_des sta_info;
+static struct rt_mutex sta_info_mutex;
+
+static struct rt_wlan_event_desc event_tab[RT_WLAN_EVT_MAX];
+
+static struct rt_wlan_complete_des *complete_tab[5];
+static struct rt_mutex complete_mutex;
+
+static struct rt_timer reconnect_time;
+
+rt_inline int _sta_is_null(void)
 {
-    WLAN_MGNT_DBG("wlan init done  event callback \n");
+    if (_sta_mgnt.device == RT_NULL)
+    {
+        return 1;
+    }
+    return 0;
 }
 
-static void wlan_mgnt_link_up_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data)
+rt_inline int _ap_is_null(void)
 {
-    WLAN_MGNT_DBG("wlan link up event callback \n");
+    if (_ap_mgnt.device == RT_NULL)
+    {
+        return 1;
+    }
+    return 0;
 }
 
-static void wlan_mgnt_link_down_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data)
+rt_inline rt_bool_t _is_do_connect(void)
 {
-    WLAN_MGNT_DBG("wlan link down event callback \n");
+    if ((rt_wlan_get_autoreconnect_mode() == RT_FALSE) ||
+            (rt_wlan_is_connected() == RT_TRUE) ||
+            (_sta_mgnt.state & RT_WLAN_STATE_CONNECTING))
+    {
+        return RT_FALSE;
+    }
+    return RT_TRUE;
 }
 
-static void wlan_mgnt_sta_connect_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data)
+static void rt_wlan_mgnt_work(void *parameter);
+
+static rt_err_t rt_wlan_send_msg(rt_wlan_dev_event_t event, void *buff, int len)
 {
-    WLAN_MGNT_DBG("wlan sta connect event callback \n");
-    struct netif *netif = device->parent.netif;
+    struct rt_wlan_msg *msg;
+
+    RT_WLAN_LOG_D("F:%s is run event:%d", __FUNCTION__, event);
+
+    /* Event packing */
+    msg = rt_malloc(sizeof(struct rt_wlan_msg) + len);
+    if (msg == RT_NULL)
+    {
+        RT_WLAN_LOG_E("wlan mgnt send msg err! No memory");
+        return -RT_ENOMEM;
+    }
+    rt_memset(msg, 0, sizeof(struct rt_wlan_msg) + len);
+    msg->event = event;
+    if (len != 0)
+    {
+        msg->buff = ((char *)msg) + sizeof(struct rt_wlan_msg);
+        msg->len = len;
+    }
+
+    /* send event to wlan thread */
+    if (rt_wlan_workqueue_dowork(rt_wlan_mgnt_work, msg) != RT_EOK)
+    {
+        rt_free(msg);
+        RT_WLAN_LOG_E("wlan mgnt do work fail");
+        return -RT_ERROR;
+    }
+    return RT_EOK;
+}
+
+static rt_err_t rt_wlan_scan_result_cache(struct rt_wlan_info *info, int timeout)
+{
+    struct rt_wlan_info *ptable;
+    rt_err_t err = RT_EOK;
+    int i, insert = -1;
+
+    if (_sta_is_null() || (info == RT_NULL)) return RT_EOK;
 
-    netifapi_netif_set_up(netif);
-    netifapi_netif_set_link_up(netif);
-#ifdef RT_LWIP_DHCP
-    /* start DHCP */
-    dhcp_start(netif);
+    RT_WLAN_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]);
+
+    err = rt_mutex_take(&scan_result_mutex, rt_tick_from_millisecond(timeout));
+    if (err != RT_EOK)
+        return err;
+
+    /* de-duplicatio */
+    for (i = 0; i < scan_result.num; i++)
+    {
+        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))
+        {
+            rt_mutex_release(&scan_result_mutex);
+            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)
+    {
+        rt_mutex_release(&scan_result_mutex);
+        RT_WLAN_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;
+    rt_mutex_release(&scan_result_mutex);
+    return err;
+}
+
+static rt_err_t rt_wlan_sta_info_add(struct rt_wlan_info *info, int timeout)
+{
+    struct rt_wlan_sta_list *sta_list;
+    rt_err_t err = RT_EOK;
+
+    if (_ap_is_null() || (info == RT_NULL)) return RT_EOK;
+
+    err = rt_mutex_take(&sta_info_mutex, rt_tick_from_millisecond(timeout));
+    if (err == RT_EOK)
+    {
+        /* malloc memory */
+        sta_list = rt_malloc(sizeof(struct rt_wlan_sta_list));
+        if (sta_list == RT_NULL)
+        {
+            rt_mutex_release(&sta_info_mutex);
+            RT_WLAN_LOG_E("sta list malloc failed!");
+            return -RT_ENOMEM;
+        }
+        sta_list->next = RT_NULL;
+        sta_list->info = *info;
+
+        /* Append sta info */
+        sta_list->next = sta_info.node;
+        sta_info.node = sta_list;
+        /* num++ */
+        sta_info.num ++;
+        rt_mutex_release(&sta_info_mutex);
+        RT_WLAN_LOG_I("sta associated mac:%02x:%02x:%02x:%02x:%02x:%02x",
+                      info->bssid[0], info->bssid[1], info->bssid[2],
+                      info->bssid[3], info->bssid[4], info->bssid[5]);
+    }
+    return err;
+}
+
+static rt_err_t rt_wlan_sta_info_del(struct rt_wlan_info *info, int timeout)
+{
+    struct rt_wlan_sta_list *sta_list, *sta_prve;
+    rt_err_t err = RT_EOK;
+
+    if (_ap_is_null() || (info == RT_NULL)) return RT_EOK;
+
+    err = rt_mutex_take(&sta_info_mutex, rt_tick_from_millisecond(timeout));
+    if (err == RT_EOK)
+    {
+        /* traversing the list */
+        for (sta_list = sta_info.node, sta_prve = RT_NULL; sta_list != RT_NULL;
+                sta_prve = sta_list, sta_list = sta_list->next)
+        {
+            /* find mac addr */
+            if (rt_memcmp(&sta_list->info.bssid[0], &info->bssid[0], RT_WLAN_BSSID_MAX_LENGTH) == 0)
+            {
+                if (sta_prve == RT_NULL)
+                {
+                    sta_info.node = sta_list->next;
+                }
+                else
+                {
+                    sta_prve->next = sta_list->next;
+                }
+                sta_info.num --;
+                rt_free(sta_list);
+                break;
+            }
+        }
+        rt_mutex_release(&sta_info_mutex);
+        RT_WLAN_LOG_I("sta exit mac:%02x:%02x:%02x:%02x:%02x:%02x",
+                      info->bssid[0], info->bssid[1], info->bssid[2],
+                      info->bssid[3], info->bssid[4], info->bssid[5]);
+    }
+    return err;
+}
+
+static rt_err_t rt_wlan_sta_info_del_all(int timeout)
+{
+    struct rt_wlan_sta_list *sta_list, *sta_next;
+    rt_err_t err = RT_EOK;
+
+    err = rt_mutex_take(&sta_info_mutex, rt_tick_from_millisecond(timeout));
+    if (err == RT_EOK)
+    {
+        /* traversing the list */
+        for (sta_list = sta_info.node; sta_list != RT_NULL; sta_list = sta_next)
+        {
+            sta_next = sta_list->next;
+            sta_info.num --;
+            rt_free(sta_list);
+        }
+        rt_mutex_release(&sta_info_mutex);
+    }
+    if (sta_info.num != 0)
+    {
+        RT_WLAN_LOG_W("\n\n!!!Program runing exception!!!\n\n");
+    }
+    sta_info.num = 0;
+    sta_info.node = RT_NULL;
+    return err;
+}
+
+static void rt_wlan_auto_connect_run(struct rt_work *work, void *parameter)
+{
+    static rt_uint32_t id = 0;
+    struct rt_wlan_cfg_info cfg_info;
+    char *password = RT_NULL;
+    rt_base_t level;
+
+    RT_WLAN_LOG_D("F:%s is run", __FUNCTION__);
+
+    if (rt_mutex_take(&mgnt_mutex, 0) != RT_EOK)
+        goto exit;
+
+    /* auto connect status is disable or wifi is connect or connecting, exit */
+    if (_is_do_connect() == RT_FALSE)
+    {
+        id = 0;
+        RT_WLAN_LOG_D("not connection");
+        goto exit;
+    }
+
+    /* Read the next configuration */
+    rt_memset(&cfg_info, 0, sizeof(struct rt_wlan_cfg_info));
+    if (rt_wlan_cfg_read_index(&cfg_info, id ++) == 0)
+    {
+        RT_WLAN_LOG_D("read cfg fail");
+        id = 0;
+        goto exit;
+    }
+
+    if (id >= rt_wlan_cfg_get_num()) id = 0;
+
+    if ((cfg_info.key.len > 0) && (cfg_info.key.len < RT_WLAN_PASSWORD_MAX_LENGTH))
+    {
+        cfg_info.key.val[cfg_info.key.len] = '\0';
+        password = (char *)(&cfg_info.key.val[0]);
+    }
+    rt_wlan_connect_adv(&cfg_info.info, password);
+exit:
+    rt_mutex_release(&mgnt_mutex);
+    level = rt_hw_interrupt_disable();
+    rt_memset(work, 0, sizeof(struct rt_work));
+    rt_hw_interrupt_enable(level);
+}
+
+static void rt_wlan_cyclic_check(void *parameter)
+{
+    struct rt_workqueue *workqueue;
+    static struct rt_work work;
+    rt_base_t level;
+
+    if ((_is_do_connect() == RT_TRUE) && (work.work_func == RT_NULL))
+    {
+        workqueue = rt_wlan_get_workqueue();
+        if (workqueue != RT_NULL)
+        {
+            level = rt_hw_interrupt_disable();
+            rt_work_init(&work, rt_wlan_auto_connect_run, RT_NULL);
+            rt_hw_interrupt_enable(level);
+            if (rt_workqueue_dowork(workqueue, &work) != RT_EOK)
+            {
+                level = rt_hw_interrupt_disable();
+                rt_memset(&work, 0, sizeof(struct rt_work));
+                rt_hw_interrupt_enable(level);
+            }
+        }
+    }
+}
+
+static void rt_wlan_mgnt_work(void *parameter)
+{
+    struct rt_wlan_msg *msg = parameter;
+
+    switch (msg->event)
+    {
+    case RT_WLAN_DEV_EVT_CONNECT:
+    {
+        struct rt_wlan_cfg_info cfg_info;
+
+        /* save config */
+        if (rt_wlan_is_connected() == RT_TRUE)
+        {
+            rt_enter_critical();
+            cfg_info.info = _sta_mgnt.info;
+            cfg_info.key = _sta_mgnt.key;
+            rt_exit_critical();
+            RT_WLAN_LOG_D("run save config! ssid:%s len%d", _sta_mgnt.info.ssid.val, _sta_mgnt.info.ssid.len);
+            rt_wlan_cfg_save(&cfg_info);
+        }
+        break;
+    }
+    default :
+        break;
+    }
+
+    rt_free(msg);
+}
+
+static void rt_wlan_event_dispatch(struct rt_wlan_device *device, rt_wlan_dev_event_t event, struct rt_wlan_buff *buff, void *parameter)
+{
+    rt_base_t level;
+    void *user_parameter;
+    rt_wlan_event_handler handler = RT_NULL;
+    rt_err_t err = RT_NULL;
+    rt_wlan_event_t user_event = RT_WLAN_EVT_MAX;
+    int i;
+    struct rt_wlan_buff user_buff = { 0 };
+
+    if (buff)
+    {
+        user_buff = *buff;
+    }
+    /* 事件处理 */
+    switch (event)
+    {
+    case RT_WLAN_DEV_EVT_CONNECT:
+    {
+        RT_WLAN_LOG_D("event: CONNECT");
+        _sta_mgnt.state |= RT_WLAN_STATE_CONNECT;
+        _sta_mgnt.state &= ~RT_WLAN_STATE_CONNECTING;
+        user_event = RT_WLAN_EVT_STA_CONNECTED;
+        TIME_STOP();
+        rt_wlan_send_msg(event, RT_NULL, 0);
+        user_buff.data = &_sta_mgnt.info;
+        user_buff.len = sizeof(struct rt_wlan_info);
+        RT_WLAN_LOG_I("wifi connect success ssid:%s", &_sta_mgnt.info.ssid.val[0]);
+        break;
+    }
+    case RT_WLAN_DEV_EVT_CONNECT_FAIL:
+    {
+        RT_WLAN_LOG_D("event: CONNECT_FAIL");
+        _sta_mgnt.state &= ~RT_WLAN_STATE_CONNECT;
+        _sta_mgnt.state &= ~RT_WLAN_STATE_CONNECTING;
+        _sta_mgnt.state &= ~RT_WLAN_STATE_READY;
+        user_event = RT_WLAN_EVT_STA_CONNECTED_FAIL;
+        user_buff.data = &_sta_mgnt.info;
+        user_buff.len = sizeof(struct rt_wlan_info);
+        TIME_START();
+        break;
+    }
+    case RT_WLAN_DEV_EVT_DISCONNECT:
+    {
+        RT_WLAN_LOG_D("event: DISCONNECT");
+        _sta_mgnt.state &= ~RT_WLAN_STATE_CONNECT;
+        _sta_mgnt.state &= ~RT_WLAN_STATE_READY;
+        user_event = RT_WLAN_EVT_STA_DISCONNECTED;
+        user_buff.data = &_sta_mgnt.info;
+        user_buff.len = sizeof(struct rt_wlan_info);
+        TIME_START();
+        break;
+    }
+    case RT_WLAN_DEV_EVT_AP_START:
+    {
+        RT_WLAN_LOG_D("event: AP_START");
+        _ap_mgnt.state |= RT_WLAN_STATE_ACTIVE;
+        user_event = RT_WLAN_EVT_AP_START;
+        user_buff.data = &_ap_mgnt.info;
+        user_buff.len = sizeof(struct rt_wlan_info);
+        break;
+    }
+    case RT_WLAN_DEV_EVT_AP_STOP:
+    {
+        RT_WLAN_LOG_D("event: AP_STOP");
+        _ap_mgnt.state &= ~RT_WLAN_STATE_ACTIVE;
+        user_event = RT_WLAN_EVT_AP_STOP;
+        err = rt_wlan_sta_info_del_all(RT_WAITING_FOREVER);
+        if (err != RT_NULL)
+        {
+            RT_WLAN_LOG_W("AP_STOP event handle fail");
+        }
+        user_buff.data = &_ap_mgnt.info;
+        user_buff.len = sizeof(struct rt_wlan_info);
+        break;
+    }
+    case RT_WLAN_DEV_EVT_AP_ASSOCIATED:
+    {
+        RT_WLAN_LOG_D("event: ASSOCIATED");
+        user_event = RT_WLAN_EVT_AP_ASSOCIATED;
+        if (user_buff.len != sizeof(struct rt_wlan_info))
+            break;
+        err = rt_wlan_sta_info_add(user_buff.data, RT_WAITING_FOREVER);
+        if (err != RT_EOK)
+        {
+            RT_WLAN_LOG_W("AP_ASSOCIATED event handle fail");
+        }
+        break;
+    }
+    case RT_WLAN_DEV_EVT_AP_DISASSOCIATED:
+    {
+        RT_WLAN_LOG_D("event: DISASSOCIATED");
+        user_event = RT_WLAN_EVT_AP_DISASSOCIATED;
+        if (user_buff.len != sizeof(struct rt_wlan_info))
+            break;
+        err = rt_wlan_sta_info_del(user_buff.data, RT_WAITING_FOREVER);
+        if (err != RT_EOK)
+        {
+            RT_WLAN_LOG_W("AP_DISASSOCIATED event handle fail");
+        }
+        break;
+    }
+    case RT_WLAN_DEV_EVT_AP_ASSOCIATE_FAILED:
+    {
+        RT_WLAN_LOG_D("event: AP_ASSOCIATE_FAILED");
+        break;
+    }
+    case RT_WLAN_DEV_EVT_SCAN_REPORT:
+    {
+        RT_WLAN_LOG_D("event: SCAN_REPORT");
+        user_event = RT_WLAN_EVT_SCAN_REPORT;
+        if (user_buff.len != sizeof(struct rt_wlan_info))
+            break;
+        rt_wlan_scan_result_cache(user_buff.data, 0);
+        break;
+    }
+    case RT_WLAN_DEV_EVT_SCAN_DONE:
+    {
+        RT_WLAN_LOG_D("event: SCAN_DONE");
+        user_buff.data = &scan_result;
+        user_buff.len = sizeof(scan_result);
+        user_event = RT_WLAN_EVT_SCAN_DONE;
+        break;
+    }
+    default :
+    {
+        RT_WLAN_LOG_D("event: UNKNOWN");
+        return;
+    }
+    }
+
+    /* send event */
+    COMPLETE_LOCK();
+    for (i = 0; i < sizeof(complete_tab) / sizeof(complete_tab[0]); i++)
+    {
+        if ((complete_tab[i] != RT_NULL))
+        {
+            complete_tab[i]->event_flag |= 0x1 << event;
+            rt_event_send(&complete_tab[i]->complete, 0x1 << event);
+            RT_WLAN_LOG_D("&complete_tab[i]->complete:0x%08x", &complete_tab[i]->complete);
+        }
+    }
+    COMPLETE_UNLOCK();
+    /* Get user callback */
+    if (user_event < RT_WLAN_EVT_MAX)
+    {
+        level = rt_hw_interrupt_disable();
+        handler = event_tab[user_event].handler;
+        user_parameter = event_tab[user_event].parameter;
+        rt_hw_interrupt_enable(level);
+    }
+
+    /* run user callback fun */
+    if (handler)
+    {
+        handler(user_event, &user_buff, user_parameter);
+    }
+}
+
+static struct rt_wlan_complete_des *rt_wlan_complete_create(const char *name)
+{
+    struct rt_wlan_complete_des *complete;
+    int i;
+
+    complete = rt_malloc(sizeof(struct rt_wlan_complete_des));
+    if (complete == RT_NULL)
+    {
+        RT_WLAN_LOG_E("complete event create failed");
+        MGNT_UNLOCK();
+        return complete;
+    }
+    rt_event_init(&complete->complete, name, RT_IPC_FLAG_FIFO);
+    complete->event_flag = 0;
+    //protect
+    COMPLETE_LOCK();
+    for (i = 0; i < sizeof(complete_tab) / sizeof(complete_tab[0]); i++)
+    {
+        if (complete_tab[i] == RT_NULL)
+        {
+            complete->index = i;
+            complete_tab[i] = complete;
+            break;
+        }
+    }
+    COMPLETE_UNLOCK();
+
+    if (i >= sizeof(complete_tab) / sizeof(complete_tab[0]))
+    {
+        rt_event_detach(&complete->complete);
+        rt_free(complete);
+        complete = RT_NULL;
+    }
+
+    return complete;
 }
 
-static void wlan_mgnt_sta_disconnect_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data)
+static rt_err_t rt_wlan_complete_wait(struct rt_wlan_complete_des *complete, rt_uint32_t event,
+                                      rt_uint32_t timeout, rt_uint32_t *recved)
 {
-    WLAN_MGNT_DBG("wlan sta disconnect event callback \n");
-    netifapi_netif_set_down(device->parent.netif);
-    netifapi_netif_set_link_down(device->parent.netif);
-    rt_memset(&device->parent.netif->ip_addr, 0, sizeof(ip_addr_t));
-    rt_memset(&device->parent.netif->netmask, 0, sizeof(ip_addr_t));
-    rt_memset(&device->parent.netif->gw, 0, sizeof(ip_addr_t));
-#ifdef RT_LWIP_DHCP
-    dhcp_stop(device->parent.netif);
+    if (complete == RT_NULL)
+    {
+        return -RT_ERROR;
+    }
+
+    /* Check whether there is a waiting event */
+    if (complete->event_flag & event)
+    {
+        *recved = complete->event_flag;
+        return RT_EOK;
+    }
+    else
+    {
+        return rt_event_recv(&complete->complete, event, RT_EVENT_FLAG_OR,
+                             rt_tick_from_millisecond(timeout), recved);
+    }
+}
+
+static void rt_wlan_complete_delete(struct rt_wlan_complete_des *complete)
+{
+    if (complete == RT_NULL)
+    {
+        return;
+    }
+    COMPLETE_LOCK();
+    complete_tab[complete->index] = RT_NULL;
+    COMPLETE_UNLOCK();
+    rt_event_detach(&complete->complete);
+    rt_free(complete);
+}
+
+rt_err_t rt_wlan_set_mode(const char *dev_name, rt_wlan_mode_t mode)
+{
+    rt_device_t device = RT_NULL;
+    rt_err_t err;
+    rt_int8_t up_event_flag = 0;
+    rt_wlan_dev_event_handler handler = RT_NULL;
+
+    if ((dev_name == RT_NULL) || (mode >= RT_WLAN_MODE_MAX))
+    {
+        RT_WLAN_LOG_E("Parameter Wrongful name:%s mode:%d", dev_name, mode);
+        return -RT_EINVAL;
+    }
+
+    RT_WLAN_LOG_D("%s is run dev_name:%s mode:%s%s%s", __FUNCTION__, dev_name,
+                  mode == RT_WLAN_NONE ? "NONE" : "",
+                  mode == RT_WLAN_STATION ? "STA" : "",
+                  mode == RT_WLAN_AP ? "AP" : ""
+                 );
+
+    /* find device */
+    device = rt_device_find(dev_name);
+    if (device == RT_NULL)
+    {
+        RT_WLAN_LOG_E("not find device, set mode failed! name:%s", dev_name);
+        return -RT_EIO;
+    }
+    if (RT_WLAN_DEVICE(device)->mode == mode)
+    {
+        RT_WLAN_LOG_D("L:%d this device mode is set");
+        return RT_EOK;
+    }
+
+    if ((mode == RT_WLAN_STATION) &&
+            (RT_WLAN_DEVICE(device)->flags & RT_WLAN_FLAG_AP_ONLY))
+    {
+        RT_WLAN_LOG_I("this device ap mode only");
+        return -RT_ERROR;
+    }
+    else if ((mode == RT_WLAN_AP) &&
+             (RT_WLAN_DEVICE(device)->flags & RT_WLAN_FLAG_STA_ONLY))
+    {
+        RT_WLAN_LOG_I("this device sta mode only");
+        return -RT_ERROR;
+    }
+    /*
+     * device == sta  and change to ap,  should deinit
+     * device == ap   and change to sta, should deinit
+    */
+    MGNT_LOCK();
+    if (((mode == RT_WLAN_STATION) && (RT_WLAN_DEVICE(device) == AP_DEVICE())) ||
+            ((mode == RT_WLAN_AP) && (RT_WLAN_DEVICE(device) == STA_DEVICE())))
+    {
+        err = rt_wlan_set_mode(dev_name, RT_WLAN_NONE);
+        if (err != RT_EOK)
+        {
+            RT_WLAN_LOG_E("change mode failed!");
+            MGNT_UNLOCK();
+            return err;
+        }
+    }
+
+    /* init device */
+    err = rt_wlan_dev_init(RT_WLAN_DEVICE(device), mode);
+    if (err != RT_EOK)
+    {
+        RT_WLAN_LOG_E("F:%s L:%d wlan init failed", __FUNCTION__, __LINE__);
+        MGNT_UNLOCK();
+        return err;
+    }
+
+    /* the mode is none */
+    if (mode == RT_WLAN_NONE)
+    {
+        if (_sta_mgnt.device == RT_WLAN_DEVICE(device))
+        {
+            _sta_mgnt.device = RT_NULL;
+            _sta_mgnt.state = 0;
+            up_event_flag = 1;
+            handler = RT_NULL;
+        }
+        else if (_ap_mgnt.device == RT_WLAN_DEVICE(device))
+        {
+            _ap_mgnt.state = 0;
+            _ap_mgnt.device = RT_NULL;
+            up_event_flag = 1;
+            handler = RT_NULL;
+        }
+    }
+    /* save sta device */
+    else if (mode == RT_WLAN_STATION)
+    {
+        up_event_flag = 1;
+        handler = rt_wlan_event_dispatch;
+        _sta_mgnt.device = RT_WLAN_DEVICE(device);
+    }
+    /* save ap device */
+    else if (mode == RT_WLAN_AP)
+    {
+        up_event_flag = 1;
+        handler = rt_wlan_event_dispatch;
+        _ap_mgnt.device = RT_WLAN_DEVICE(device);
+    }
+
+    /* update dev event handle */
+    if (up_event_flag == 1)
+    {
+        rt_wlan_dev_event_t event;
+        for (event = RT_WLAN_DEV_EVT_INIT_DONE; event < RT_WLAN_DEV_EVT_MAX; event++)
+        {
+            if (handler)
+            {
+                rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), event, handler, RT_NULL);
+            }
+            else
+            {
+                rt_wlan_dev_unregister_event_handler(RT_WLAN_DEVICE(device), event, handler);
+            }
+        }
+    }
+    MGNT_UNLOCK();
+
+    /* Mount protocol */
+#ifdef RT_WLAN_DEFAULT_PROT
+    rt_wlan_prot_attach(dev_name, RT_WLAN_DEFAULT_PROT);
 #endif
+    return err;
+}
+
+rt_wlan_mode_t rt_wlan_get_mode(const char *dev_name)
+{
+    rt_device_t device = RT_NULL;
+    rt_wlan_mode_t mode;
+
+    if (dev_name == RT_NULL)
+    {
+        RT_WLAN_LOG_E("name is null");
+        return RT_WLAN_NONE;
+    }
+
+    /* find device */
+    device = rt_device_find(dev_name);
+    if (device == RT_NULL)
+    {
+        RT_WLAN_LOG_E("device not find! name:%s", dev_name);
+        return RT_WLAN_NONE;
+    }
+
+    /* get mode */
+    mode = RT_WLAN_DEVICE(device)->mode;
+    RT_WLAN_LOG_D("%s is run dev_name:%s mode:%s%s%s", __FUNCTION__, dev_name,
+                  mode == RT_WLAN_NONE ? "NONE" : "",
+                  mode == RT_WLAN_STATION ? "STA" : "",
+                  mode == RT_WLAN_AP ? "AP" : "");
+
+    return mode;
+}
+
+rt_bool_t rt_wlan_find_best_by_cache(const char *ssid, struct rt_wlan_info *info)
+{
+    int i, ssid_len;
+    struct rt_wlan_info *info_best;
+    struct rt_wlan_scan_result *result;
+
+    ssid_len = rt_strlen(ssid);
+    result = &scan_result;
+    info_best = RT_NULL;
+
+    SRESULT_LOCK();
+    for (i = 0; i < result->num; i++)
+    {
+        /* SSID is equal. */
+        if ((result->info[i].ssid.len == ssid_len) &&
+                (rt_memcmp((char *)&result->info[i].ssid.val[0], ssid, ssid_len) == 0))
+        {
+            if (info_best == RT_NULL)
+            {
+                info_best = &result->info[i];
+                continue;
+            }
+            /* Signal strength effective */
+            if ((result->info[i].rssi < 0) && (info_best->rssi < 0))
+            {
+                /* Find the strongest signal. */
+                if (result->info[i].rssi > info_best->rssi)
+                {
+                    info_best = &result->info[i];
+                    continue;
+                }
+                else if (result->info[i].rssi < info_best->rssi)
+                {
+                    continue;
+                }
+            }
+
+            /* Finding the fastest signal */
+            if (result->info[i].datarate > info_best->datarate)
+            {
+                info_best = &result->info[i];
+                continue;
+            }
+        }
+    }
+    SRESULT_UNLOCK();
+
+    if (info_best == RT_NULL)
+        return RT_FALSE;
+
+    *info = *info_best;
+    return RT_TRUE;
+}
+
+rt_err_t rt_wlan_connect(const char *ssid, const char *password)
+{
+    rt_err_t err = RT_EOK;
+    int ssid_len = 0;
+    struct rt_wlan_info info;
+    struct rt_wlan_complete_des *complete;
+    rt_uint32_t set = 0, recved = 0;
+
+    /* sta dev Can't be NULL */
+    if (_sta_is_null())
+    {
+        return -RT_EIO;
+    }
+    RT_WLAN_LOG_D("%s is run ssid:%s password:%s", __FUNCTION__, ssid, password);
+    if (ssid == RT_NULL)
+    {
+        RT_WLAN_LOG_E("ssid is null!");
+        return -RT_EINVAL;
+    }
+    ssid_len = rt_strlen(ssid);
+    if (ssid_len > RT_WLAN_SSID_MAX_LENGTH)
+    {
+        RT_WLAN_LOG_E("ssid is to long! ssid:%s len:%d", ssid, ssid_len);
+        return -RT_EINVAL;
+    }
+
+    if ((rt_wlan_is_connected() == RT_TRUE) &&
+            (rt_strcmp((char *)&_sta_mgnt.info.ssid.val[0], ssid) == 0))
+    {
+        RT_WLAN_LOG_I("wifi is connect ssid:%s", ssid);
+        return RT_EOK;
+    }
+    /* get info from cache */
+    INVALID_INFO(&info);
+    MGNT_LOCK();
+    if (rt_wlan_find_best_by_cache(ssid, &info) != RT_TRUE)
+    {
+        rt_wlan_scan_sync();
+        rt_wlan_find_best_by_cache(ssid, &info);
+        rt_wlan_scan_result_clean();
+    }
+
+    if (info.ssid.len <= 0)
+    {
+        RT_WLAN_LOG_W("not find ap! ssid:%s", ssid);
+        MGNT_UNLOCK();
+        return -RT_ERROR;
+    }
+
+    RT_WLAN_LOG_D("find best info ssid:%s mac: %02x %02x %02x %02x %02x %02x",
+                  info.ssid.val, info.bssid[0], info.bssid[1], info.bssid[2], info.bssid[3], info.bssid[4], info.bssid[5]);
+
+    /* create event wait complete */
+    complete = rt_wlan_complete_create("join");
+    if (complete == RT_NULL)
+    {
+        MGNT_UNLOCK();
+        return -RT_ENOMEM;
+    }
+    /* run connect adv */
+    err = rt_wlan_connect_adv(&info, password);
+    if (err != RT_EOK)
+    {
+        rt_wlan_complete_delete(complete);
+        MGNT_UNLOCK();
+        return err;
+    }
+
+    /* Initializing events that need to wait */
+    set |= 0x1 << RT_WLAN_DEV_EVT_CONNECT;
+    set |= 0x1 << RT_WLAN_DEV_EVT_CONNECT_FAIL;
+    /* Check whether there is a waiting event */
+    rt_wlan_complete_wait(complete, set, RT_WLAN_CONNECT_WAIT_MS, &recved);
+    rt_wlan_complete_delete(complete);
+    /* check event */
+    set = 0x1 << RT_WLAN_DEV_EVT_CONNECT;
+    if (!(recved & set))
+    {
+        RT_WLAN_LOG_I("wifi connect failed!");
+        MGNT_UNLOCK();
+        return -RT_ERROR;
+    }
+    MGNT_UNLOCK();
+    return err;
+}
+
+rt_err_t rt_wlan_connect_adv(struct rt_wlan_info *info, const char *password)
+{
+    int password_len = 0;
+    rt_err_t err = RT_EOK;
+
+    if (_sta_is_null())
+    {
+        return -RT_EIO;
+    }
+    if (info == RT_NULL)
+    {
+        RT_WLAN_LOG_E("info is null!");
+        return -RT_EINVAL;
+    }
+    RT_WLAN_LOG_D("%s is run ssid:%s password:%s", __FUNCTION__, info->ssid.val, password);
+    /* Parameter checking */
+    if (password != RT_NULL)
+    {
+        password_len = rt_strlen(password);
+        if (password_len > RT_WLAN_PASSWORD_MAX_LENGTH)
+        {
+            RT_WLAN_LOG_E("password is to long! password:%s len:%d", password, password_len);
+            return -RT_EINVAL;
+        }
+    }
+    if (info->ssid.len == 0 || info->ssid.len > RT_WLAN_SSID_MAX_LENGTH)
+    {
+        RT_WLAN_LOG_E("ssid is zero or to long! ssid:%s len:%d", info->ssid.val, info->ssid.len);
+        return -RT_EINVAL;
+    }
+    /* is connect ? */
+    MGNT_LOCK();
+    if (rt_wlan_is_connected())
+    {
+        if ((_sta_mgnt.info.ssid.len == info->ssid.len) &&
+                (_sta_mgnt.key.len == password_len) &&
+                (rt_memcmp(&_sta_mgnt.info.ssid.val[0], &info->ssid.val[0], info->ssid.len) == 0) &&
+                (rt_memcmp(&_sta_mgnt.info.bssid[0], &info->bssid[0], RT_WLAN_BSSID_MAX_LENGTH) == 0) &&
+                (rt_memcmp(&_sta_mgnt.key.val[0], password, password_len) == 0))
+        {
+            RT_WLAN_LOG_I("wifi Already Connected");
+            MGNT_UNLOCK();
+            return RT_EOK;
+        }
+
+        err = rt_wlan_disconnect();
+        if (err != RT_EOK)
+        {
+            MGNT_UNLOCK();
+            return err;
+        }
+    }
+
+    /* save info */
+    rt_enter_critical();
+    _sta_mgnt.info = *info;
+    rt_memcpy(&_sta_mgnt.key.val, password, password_len);
+    _sta_mgnt.key.len = password_len;
+    _sta_mgnt.key.val[password_len] = '\0';
+    rt_exit_critical();
+    /* run wifi connect */
+    _sta_mgnt.state |= RT_WLAN_STATE_CONNECTING;
+    err = rt_wlan_dev_connect(_sta_mgnt.device, info, password, password_len);
+    if (err != RT_EOK)
+    {
+        rt_enter_critical();
+        rt_memset(&_sta_mgnt.info, 0, sizeof(struct rt_wlan_ssid));
+        rt_memset(&_sta_mgnt.key, 0, sizeof(struct rt_wlan_key));
+        rt_exit_critical();
+        _sta_mgnt.state &= ~RT_WLAN_STATE_CONNECTING;
+        MGNT_UNLOCK();
+        return err;
+    }
+
+    MGNT_UNLOCK();
+    return err;
+}
+
+rt_err_t rt_wlan_disconnect(void)
+{
+    rt_err_t err;
+    struct rt_wlan_complete_des *complete;
+    rt_uint32_t recved = 0, set = 0;
+
+    /* ap dev Can't be empty */
+    if (_sta_is_null())
+    {
+        return -RT_EIO;
+    }
+    RT_WLAN_LOG_D("%s is run", __FUNCTION__);
+
+    /* run disconnect */
+    MGNT_LOCK();
+    /* create event wait complete */
+    complete = rt_wlan_complete_create("disc");
+    if (complete == RT_NULL)
+    {
+        MGNT_UNLOCK();
+        return -RT_ENOMEM;
+    }
+    err = rt_wlan_dev_disconnect(_sta_mgnt.device);
+    if (err != RT_EOK)
+    {
+        RT_WLAN_LOG_E("wifi disconnect fail");
+        rt_wlan_complete_delete(complete);
+        MGNT_UNLOCK();
+        return err;
+    }
+    /* Initializing events that need to wait */
+    set |= 0x1 << RT_WLAN_DEV_EVT_DISCONNECT;
+    /* Check whether there is a waiting event */
+    rt_wlan_complete_wait(complete, set, RT_WLAN_CONNECT_WAIT_MS, &recved);
+    rt_wlan_complete_delete(complete);
+    /* check event */
+    set = 0x1 << RT_WLAN_DEV_EVT_DISCONNECT;
+    if (!(recved & set))
+    {
+        RT_WLAN_LOG_E("disconnect failed!");
+        MGNT_UNLOCK();
+        return -RT_ERROR;
+    }
+    RT_WLAN_LOG_I("disconnect success!");
+    MGNT_UNLOCK();
+    return err;
+}
+
+rt_bool_t rt_wlan_is_connected(void)
+{
+    rt_bool_t _connect;
+
+    if (_sta_is_null())
+    {
+        return RT_FALSE;
+    }
+    _connect = _sta_mgnt.state & RT_WLAN_STATE_CONNECT ? RT_TRUE : RT_FALSE;
+    RT_WLAN_LOG_D("%s is run : %s", __FUNCTION__, _connect ? "connect" : "disconnect");
+    return _connect;
+}
+
+rt_bool_t rt_wlan_is_ready(void)
+{
+    rt_bool_t _ready;
+
+    if (_sta_is_null())
+    {
+        return RT_FALSE;
+    }
+    _ready = _sta_mgnt.state & RT_WLAN_STATE_READY ? RT_TRUE : RT_FALSE;
+    RT_WLAN_LOG_D("%s is run : %s", __FUNCTION__, _ready ? "ready" : "not ready");
+    return _ready;
+}
+
+rt_err_t rt_wlan_set_mac(rt_uint8_t mac[6])
+{
+    rt_err_t err = RT_EOK;
+
+    if (_sta_is_null())
+    {
+        return -RT_EIO;
+    }
+    RT_WLAN_LOG_D("%s is run mac: %02x:%02x:%02x:%02x:%02x:%02x",
+                  __FUNCTION__, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+    MGNT_LOCK();
+    err = rt_wlan_dev_set_mac(STA_DEVICE(), mac);
+    if (err != RT_EOK)
+    {
+        RT_WLAN_LOG_E("set sta mac addr fail");
+        MGNT_UNLOCK();
+        return err;
+    }
+    MGNT_UNLOCK();
+    return err;
+}
+
+rt_err_t rt_wlan_get_mac(rt_uint8_t mac[6])
+{
+    rt_err_t err = RT_EOK;
+
+    if (_sta_is_null())
+    {
+        return -RT_EIO;
+    }
+    MGNT_LOCK();
+    err = rt_wlan_dev_get_mac(STA_DEVICE(), mac);
+    if (err != RT_EOK)
+    {
+        RT_WLAN_LOG_E("get sta mac addr fail");
+        MGNT_UNLOCK();
+        return err;
+    }
+    RT_WLAN_LOG_D("%s is run mac: %02x:%02x:%02x:%02x:%02x:%02x",
+                  __FUNCTION__, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+    MGNT_UNLOCK();
+    return err;
+}
+
+rt_err_t rt_wlan_get_info(struct rt_wlan_info *info)
+{
+    if (_sta_is_null())
+    {
+        return -RT_EIO;
+    }
+    RT_WLAN_LOG_D("%s is run", __FUNCTION__);
+
+    rt_enter_critical();
+    *info = _sta_mgnt.info;
+    rt_exit_critical();
+    return RT_EOK;
+}
+
+int rt_wlan_get_rssi(void)
+{
+    int rssi = 0;
+
+    if (_sta_is_null())
+    {
+        return -RT_EIO;
+    }
+
+    MGNT_LOCK();
+    rssi = rt_wlan_dev_get_rssi(STA_DEVICE());
+    RT_WLAN_LOG_D("%s is run rssi:%d", __FUNCTION__, rssi);
+    MGNT_UNLOCK();
+    return rssi;
+}
+
+rt_err_t rt_wlan_start_ap(const char *ssid, const char *password)
+{
+    rt_err_t err = RT_EOK;
+    int ssid_len = 0;
+    struct rt_wlan_info info;
+    struct rt_wlan_complete_des *complete;
+    rt_uint32_t set = 0, recved = 0;
+
+    if (_ap_is_null())
+    {
+        return -RT_EIO;
+    }
+    if (ssid == RT_NULL) return -RT_EINVAL;
+
+    rt_memset(&info, 0, sizeof(struct rt_wlan_info));
+    RT_WLAN_LOG_D("%s is run ssid:%s password:%s", __FUNCTION__, ssid, password);
+    if (password)
+    {
+        info.security = SECURITY_WPA2_AES_PSK;
+    }
+    ssid_len = rt_strlen(ssid);
+    if (ssid_len > RT_WLAN_SSID_MAX_LENGTH)
+    {
+        RT_WLAN_LOG_E("ssid is to long! len:%d", ssid_len);
+    }
+
+    /* copy info */
+    rt_memcpy(&info.ssid.val, ssid, ssid_len);
+    info.ssid.len = ssid_len;
+    info.channel = 6;
+
+    /* Initializing events that need to wait */
+    MGNT_LOCK();
+    /* create event wait complete */
+    complete = rt_wlan_complete_create("start_ap");
+    if (complete == RT_NULL)
+    {
+        MGNT_UNLOCK();
+        return -RT_ENOMEM;
+    }
+
+    /* start ap */
+    err = rt_wlan_start_ap_adv(&info, password);
+    if (err != RT_EOK)
+    {
+        rt_wlan_complete_delete(complete);
+        RT_WLAN_LOG_I("start ap failed!");
+        MGNT_UNLOCK();
+        return err;
+    }
+
+    /* Initializing events that need to wait */
+    set |= 0x1 << RT_WLAN_DEV_EVT_AP_START;
+    set |= 0x1 << RT_WLAN_DEV_EVT_AP_STOP;
+    /* Check whether there is a waiting event */
+    rt_wlan_complete_wait(complete, set, RT_WLAN_START_AP_WAIT_MS, &recved);
+    rt_wlan_complete_delete(complete);
+    /* check event */
+    set = 0x1 << RT_WLAN_DEV_EVT_AP_START;
+    if (!(recved & set))
+    {
+        RT_WLAN_LOG_I("start ap failed!");
+        MGNT_UNLOCK();
+        return -RT_ERROR;
+    }
+    RT_WLAN_LOG_I("start ap successs!");
+    MGNT_UNLOCK();
+    return err;
+}
+
+rt_err_t rt_wlan_start_ap_adv(struct rt_wlan_info *info, const char *password)
+{
+    rt_err_t err = RT_EOK;
+    int password_len = 0;
+
+    if (_ap_is_null())
+    {
+        return -RT_EIO;
+    }
+    RT_WLAN_LOG_D("%s is run", __FUNCTION__);
+    password_len = rt_strlen(password);
+    if (password_len > RT_WLAN_PASSWORD_MAX_LENGTH)
+    {
+        RT_WLAN_LOG_E("key is to long! len:%d", password_len);
+        return -RT_EINVAL;
+    }
+    /* is start up ? */
+    MGNT_LOCK();
+    if (rt_wlan_ap_is_active())
+    {
+        if ((_ap_mgnt.info.ssid.len == info->ssid.len) &&
+                (_ap_mgnt.info.security == info->security) &&
+                (_ap_mgnt.info.channel == info->channel) &&
+                (_ap_mgnt.info.hidden == info->hidden) &&
+                (_ap_mgnt.key.len == password_len) &&
+                (rt_memcmp(&_ap_mgnt.info.ssid.val[0], &info->ssid.val[0], info->ssid.len) == 0) &&
+                (rt_memcmp(&_ap_mgnt.key.val[0], password, password_len)))
+        {
+            RT_WLAN_LOG_D("wifi Already Start");
+            MGNT_UNLOCK();
+            return RT_EOK;
+        }
+    }
+
+    err = rt_wlan_dev_ap_start(AP_DEVICE(), info, password, password_len);
+    if (err != RT_EOK)
+    {
+        MGNT_UNLOCK();
+        return err;
+    }
+    rt_memcpy(&_ap_mgnt.info, info, sizeof(struct rt_wlan_info));
+    rt_memcpy(&_ap_mgnt.key.val, password, password_len);
+    _ap_mgnt.key.len = password_len;
+
+    MGNT_UNLOCK();
+    return err;
+}
+
+int rt_wlan_ap_is_active(void)
+{
+    int _active = 0;
+
+    if (_ap_is_null())
+    {
+        return 0;
+    }
+
+    _active = _ap_mgnt.state & RT_WLAN_STATE_ACTIVE ? 1 : 0;
+    RT_WLAN_LOG_D("%s is run active:%s", __FUNCTION__, _active ? "Active" : "Inactive");
+    return _active;
+}
+
+rt_err_t rt_wlan_ap_stop(void)
+{
+    rt_err_t err = RT_EOK;
+    struct rt_wlan_complete_des *complete;
+    rt_uint32_t set = 0, recved = 0;
+
+    if (_ap_is_null())
+    {
+        return -RT_EIO;
+    }
+    RT_WLAN_LOG_D("%s is run", __FUNCTION__);
+
+    MGNT_LOCK();
+    /* create event wait complete */
+    complete = rt_wlan_complete_create("stop_ap");
+    if (complete == RT_NULL)
+    {
+        MGNT_UNLOCK();
+        return -RT_ENOMEM;
+    }
+    err = rt_wlan_dev_ap_stop(AP_DEVICE());
+    if (err != RT_EOK)
+    {
+        RT_WLAN_LOG_E("ap stop fail");
+        rt_wlan_complete_delete(complete);
+        MGNT_UNLOCK();
+        return err;
+    }
+    /* Initializing events that need to wait */
+    set |= 0x1 << RT_WLAN_DEV_EVT_AP_STOP;
+    /* Check whether there is a waiting event */
+    rt_wlan_complete_wait(complete, set, RT_WLAN_START_AP_WAIT_MS, &recved);
+    rt_wlan_complete_delete(complete);
+    /* check event */
+    set = 0x1 << RT_WLAN_DEV_EVT_AP_STOP;
+    if (!(recved & set))
+    {
+        RT_WLAN_LOG_I("ap stop failed!");
+        MGNT_UNLOCK();
+        return -RT_ERROR;
+    }
+    RT_WLAN_LOG_I("ap stop success!");
+    MGNT_UNLOCK();
+    return err;
+}
+
+rt_err_t rt_wlan_ap_get_info(struct rt_wlan_info *info)
+{
+    if (_ap_is_null())
+    {
+        return -RT_EIO;
+    }
+    RT_WLAN_LOG_D("%s is run", __FUNCTION__);
+
+    *info = _ap_mgnt.info;
+    return RT_EOK;
+}
+
+/* get sta number  */
+int rt_wlan_ap_get_sta_num(void)
+{
+    int sta_num = 0;
+
+    STAINFO_LOCK();
+    sta_num = sta_info.num;
+    STAINFO_UNLOCK();
+    RT_WLAN_LOG_D("%s is run num:%d", __FUNCTION__, sta_num);
+    return sta_num;
+}
+
+/* get sta info */
+int rt_wlan_ap_get_sta_info(struct rt_wlan_info *info, int num)
+{
+    int sta_num = 0, i = 0;
+    struct rt_wlan_sta_list *sta_list;
+
+    STAINFO_LOCK();
+    /* sta_num = min(sta_info.num, num) */
+    sta_num = sta_info.num > num ? num : sta_info.num;
+    for (sta_list = sta_info.node; sta_list != RT_NULL && i < sta_num; sta_list = sta_list->next)
+    {
+        info[i] = sta_list->info;
+        i ++;
+    }
+    STAINFO_UNLOCK();
+    RT_WLAN_LOG_D("%s is run num:%d", __FUNCTION__, i);
+    return i;
+}
+
+/* deauth sta */
+rt_err_t rt_wlan_ap_deauth_sta(rt_uint8_t *mac)
+{
+    rt_err_t err = RT_EOK;
+    struct rt_wlan_sta_list *sta_list;
+    rt_bool_t find_flag = RT_FALSE;
+
+    if (_ap_is_null())
+    {
+        return -RT_EIO;
+    }
+    RT_WLAN_LOG_D("%s is run mac: %02x:%02x:%02x:%02x:%02x:%02x:%d",
+                  __FUNCTION__, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+    if (mac == RT_NULL)
+    {
+        RT_WLAN_LOG_E("mac addr is null");
+        return -RT_EINVAL;
+    }
+
+    MGNT_LOCK();
+    if (sta_info.node == RT_NULL || sta_info.num == 0)
+    {
+        RT_WLAN_LOG_E("No AP");
+        MGNT_UNLOCK();
+        return -RT_ERROR;
+    }
+
+    STAINFO_LOCK();
+    /* Search for MAC address from sta list */
+    for (sta_list = sta_info.node; sta_list != RT_NULL; sta_list = sta_list->next)
+    {
+        if (rt_memcmp(&sta_list->info.bssid[0], &mac[0], RT_WLAN_BSSID_MAX_LENGTH) == 0)
+        {
+            find_flag = RT_TRUE;
+            break;
+        }
+    }
+    STAINFO_UNLOCK();
+
+    /* No MAC address was found. return */
+    if (find_flag != RT_TRUE)
+    {
+        RT_WLAN_LOG_E("Not find mac addr");
+        MGNT_UNLOCK();
+        return -RT_ERROR;
+    }
+
+    /* Kill STA */
+    err = rt_wlan_dev_ap_deauth(AP_DEVICE(), mac);
+    if (err != RT_NULL)
+    {
+        RT_WLAN_LOG_E("deauth sta failed");
+        MGNT_UNLOCK();
+        return err;
+    }
+
+    MGNT_UNLOCK();
+    return err;
+}
+
+rt_err_t rt_wlan_ap_set_country(rt_country_code_t country_code)
+{
+    rt_err_t err = RT_EOK;
+
+    if (_ap_is_null())
+    {
+        return -RT_EIO;
+    }
+    RT_WLAN_LOG_D("%s is run country:%d", __FUNCTION__, country_code);
+    MGNT_LOCK();
+    err = rt_wlan_dev_set_country(AP_DEVICE(), country_code);
+    MGNT_UNLOCK();
+    return err;
+}
+
+rt_country_code_t rt_wlan_ap_get_country(void)
+{
+    rt_country_code_t country_code = RT_COUNTRY_UNKNOWN;
+
+    if (_ap_is_null())
+    {
+        return country_code;
+    }
+    MGNT_LOCK();
+    country_code = rt_wlan_dev_get_country(AP_DEVICE());
+    RT_WLAN_LOG_D("%s is run country:%d", __FUNCTION__, country_code);
+    MGNT_UNLOCK();
+    return country_code;
+}
+
+void rt_wlan_config_autoreconnect(rt_bool_t enable)
+{
+    RT_WLAN_LOG_D("%s is run enable:%d", __FUNCTION__, enable);
+
+    MGNT_LOCK();
+    if (enable)
+    {
+        _sta_mgnt.flags |= RT_WLAN_STATE_AUTOEN;
+    }
+    else
+    {
+        _sta_mgnt.flags &= ~RT_WLAN_STATE_AUTOEN;
+    }
+    MGNT_UNLOCK();
+}
+
+rt_bool_t rt_wlan_get_autoreconnect_mode(void)
+{
+    rt_bool_t enable = 0;
+
+    enable = _sta_mgnt.flags & RT_WLAN_STATE_AUTOEN ? 1 : 0;
+    RT_WLAN_LOG_D("%s is run enable:%d", __FUNCTION__, enable);
+    return enable;
+}
+
+/* Call the underlying scan function, which is asynchronous.
+The hotspots scanned are returned by callbacks */
+rt_err_t rt_wlan_scan(void)
+{
+    rt_err_t err = RT_EOK;
+
+    if (_sta_is_null())
+    {
+        return -RT_EIO;
+    }
+    RT_WLAN_LOG_D("%s is run", __FUNCTION__);
+
+    MGNT_LOCK();
+    err = rt_wlan_dev_scan(STA_DEVICE(), RT_NULL);
+    MGNT_UNLOCK();
+    return err;
+}
+
+struct rt_wlan_scan_result *rt_wlan_scan_sync(void)
+{
+    struct rt_wlan_scan_result *result;
+
+    /* Execute synchronous scan function */
+    MGNT_LOCK();
+    result = rt_wlan_scan_with_info(RT_NULL);
+    MGNT_UNLOCK();
+    return result;
+}
+
+struct rt_wlan_scan_result *rt_wlan_scan_with_info(struct rt_wlan_info *info)
+{
+    rt_err_t err = RT_EOK;
+    struct rt_wlan_complete_des *complete;
+    rt_uint32_t set = 0, recved = 0;
+
+    if (_sta_is_null())
+    {
+        return RT_NULL;
+    }
+    RT_WLAN_LOG_D("%s is run", __FUNCTION__);
+    if (info != RT_NULL && info->ssid.len > RT_WLAN_SSID_MAX_LENGTH)
+    {
+        RT_WLAN_LOG_E("ssid is to long!");
+        return RT_NULL;
+    }
+
+    /* Create an event that needs to wait. */
+    MGNT_LOCK();
+    complete = rt_wlan_complete_create("scan");
+    if (complete == RT_NULL)
+    {
+        MGNT_UNLOCK();
+        return &scan_result;
+    }
+
+    /* run scna */
+    err = rt_wlan_dev_scan(STA_DEVICE(), info);
+    if (err != RT_EOK)
+    {
+        rt_wlan_complete_delete(complete);
+        RT_WLAN_LOG_E("scna sync fail");
+        MGNT_UNLOCK();
+        return RT_NULL;
+    }
+
+    /* Initializing events that need to wait */
+    set |= 0x1 << RT_WLAN_DEV_EVT_SCAN_DONE;
+    /* Check whether there is a waiting event */
+    rt_wlan_complete_wait(complete, set, RT_WLAN_CONNECT_WAIT_MS, &recved);
+    rt_wlan_complete_delete(complete);
+    /* check event */
+    set = 0x1 << RT_WLAN_DEV_EVT_SCAN_DONE;
+    if (!(recved & set))
+    {
+        RT_WLAN_LOG_E("scna wait timeout!");
+        MGNT_UNLOCK();
+        return &scan_result;
+    }
+
+    MGNT_UNLOCK();
+    return &scan_result;
+}
+
+int rt_wlan_scan_get_info_num(void)
+{
+    int num = 0;
+
+    num = scan_result.num;
+    RT_WLAN_LOG_D("%s is run num:%d", __FUNCTION__, num);
+    return num;
 }
 
-static void wlan_mgnt_ap_start_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data)
+int rt_wlan_scan_get_info(struct rt_wlan_info *info, int num)
 {
-    WLAN_MGNT_DBG("wlan ap start event callback \n");
-    netifapi_netif_set_up(device->parent.netif);
-    netifapi_netif_set_link_up(device->parent.netif);
+    int _num = 0;
 
-    wifi_softap_setup_netif(device->parent.netif);
+    SRESULT_LOCK();
+    if (scan_result.num && num > 0)
+    {
+        _num = scan_result.num > num ? num : scan_result.num;
+        rt_memcpy(info, scan_result.info, _num * sizeof(struct rt_wlan_info));
+    }
+    SRESULT_UNLOCK();
+    return _num;
 }
 
+struct rt_wlan_scan_result *rt_wlan_scan_get_result(void)
+{
+    return &scan_result;
+}
 
-static void wlan_mgnt_ap_stop_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data)
+void rt_wlan_scan_result_clean(void)
 {
-    WLAN_MGNT_DBG("wlan ap stop event callback \n");
+    MGNT_LOCK();
+    SRESULT_LOCK();
 
-    netifapi_netif_set_down(device->parent.netif);
-    netifapi_netif_set_link_down(device->parent.netif);
+    /* If there is data */
+    if (scan_result.num)
+    {
+        scan_result.num = 0;
+        rt_free(scan_result.info);
+        scan_result.info = RT_NULL;
+    }
+    SRESULT_UNLOCK();
+    MGNT_UNLOCK();
 }
 
-static void wlan_mgnt_ap_associate_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data)
+int rt_wlan_scan_find_cache(struct rt_wlan_info *info, struct rt_wlan_info *out_info, int num)
 {
-    WLAN_MGNT_DBG("wlan ap associate event callback \n");
+    int i = 0, count = 0;
+    struct rt_wlan_info *scan_info;
+    rt_bool_t is_equ = 1;
+    rt_uint8_t bssid_zero[RT_WLAN_BSSID_MAX_LENGTH] = { 0 };
+
+    if ((out_info == RT_NULL) || (info == RT_NULL) || (num <= 0))
+    {
+        return 0;
+    }
+    SRESULT_LOCK();
+    /* Traversing the cache to find a qualified hot spot information */
+    for (i = 0; (i < scan_result.num) && (count < num); i++)
+    {
+        scan_info = &scan_result.info[i];
+
+        if (is_equ && (info->security != SECURITY_UNKNOWN))
+        {
+            is_equ &= info->security == scan_info->security;
+        }
+        if (is_equ && ((info->ssid.len > 0) && (info->ssid.len == scan_info->ssid.len)))
+        {
+            is_equ &= rt_memcmp(&info->ssid.val[0], &scan_info->ssid.val[0], scan_info->ssid.len) == 0;
+        }
+        if (is_equ && (rt_memcmp(&info->bssid[0], bssid_zero, RT_WLAN_BSSID_MAX_LENGTH)))
+        {
+            is_equ &= rt_memcmp(&info->bssid[0], &scan_info->bssid[0], RT_WLAN_BSSID_MAX_LENGTH) == 0;
+        }
+        if (is_equ && info->datarate)
+        {
+            is_equ &= info->datarate == scan_info->datarate;
+        }
+        if (is_equ && (info->channel >= 0))
+        {
+            is_equ &= info->channel == scan_info->channel;
+        }
+        if (is_equ && (info->rssi < 0))
+        {
+            is_equ &= info->rssi == scan_info->rssi;
+        }
+        /* Determine whether to find */
+        if (is_equ)
+        {
+            rt_memcpy(&out_info[count], scan_info, sizeof(struct rt_wlan_info));
+            count ++;
+        }
+    }
+    SRESULT_UNLOCK();
+
+    return count;
 }
 
-static void wlan_mgnt_ap_disassociate_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data)
+rt_err_t rt_wlan_set_powersave(int level)
 {
-    WLAN_MGNT_DBG("wlan ap disassociate event callback \n");
+    rt_err_t err = RT_EOK;
+
+    if (_sta_is_null())
+    {
+        return -RT_EIO;
+    }
+    RT_WLAN_LOG_D("%s is run", __FUNCTION__);
+    MGNT_LOCK();
+    err = rt_wlan_dev_set_powersave(STA_DEVICE(), level);
+    MGNT_UNLOCK();
+    return err;
 }
 
-static void wlan_mgnt_scan_done_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data)
+int rt_wlan_get_powersave(void)
 {
-    WLAN_MGNT_DBG("wlan scan done event callback \n");
+    int level;
+
+    if (_sta_is_null())
+    {
+        return -1;
+    }
+    RT_WLAN_LOG_D("%s is run", __FUNCTION__);
+    MGNT_LOCK();
+    level = rt_wlan_dev_get_powersave(STA_DEVICE());
+    MGNT_UNLOCK();
+    return level;
 }
 
-int rt_wlan_mgnt_attach(struct rt_wlan_device *device, void *user_data)
+rt_err_t rt_wlan_register_event_handler(rt_wlan_event_t event, rt_wlan_event_handler handler, void *parameter)
 {
-    RT_ASSERT(device != RT_NULL);
+    rt_base_t level;
+
+    if (event >= RT_WLAN_EVT_MAX)
+    {
+        return RT_EINVAL;
+    }
+    RT_WLAN_LOG_D("%s is run event:%d", __FUNCTION__, event);
 
-    rt_wlan_register_event_handler(device, WIFI_EVT_INIT_DONE, wlan_mgnt_init_done_event);
-    rt_wlan_register_event_handler(device, WIFI_EVT_LINK_DOWN, wlan_mgnt_link_up_event);
-    rt_wlan_register_event_handler(device, WIFI_EVT_LINK_UP, wlan_mgnt_link_down_event);
-    rt_wlan_register_event_handler(device, WIFI_EVT_CONNECT, wlan_mgnt_sta_connect_event);
-    rt_wlan_register_event_handler(device, WIFI_EVT_DISCONNECT, wlan_mgnt_sta_disconnect_event);
-    rt_wlan_register_event_handler(device, WIFI_EVT_AP_START, wlan_mgnt_ap_start_event);
-    rt_wlan_register_event_handler(device, WIFI_EVT_AP_STOP, wlan_mgnt_ap_stop_event);
-    rt_wlan_register_event_handler(device, WIFI_EVENT_STA_ASSOC, wlan_mgnt_ap_associate_event);
-    rt_wlan_register_event_handler(device, WIFI_EVENT_STA_DISASSOC, wlan_mgnt_ap_disassociate_event);
-    rt_wlan_register_event_handler(device, WIFI_EVT_SCAN_DONE, wlan_mgnt_scan_done_event);
+    MGNT_UNLOCK();
+    /* Registering Callbacks */
+    level = rt_hw_interrupt_disable();
+    event_tab[event].handler = handler;
+    event_tab[event].parameter = parameter;
+    rt_hw_interrupt_enable(level);
+    MGNT_UNLOCK();
+    return RT_EOK;
+}
 
+rt_err_t rt_wlan_unregister_event_handler(rt_wlan_event_t event)
+{
+    rt_base_t level;
+
+    if (event >= RT_WLAN_EVT_MAX)
+    {
+        return RT_EINVAL;
+    }
+    RT_WLAN_LOG_D("%s is run event:%d", __FUNCTION__, event);
+    MGNT_LOCK();
+    /* unregister*/
+    level = rt_hw_interrupt_disable();
+    event_tab[event].handler = RT_NULL;
+    event_tab[event].parameter = RT_NULL;
+    rt_hw_interrupt_enable(level);
+    MGNT_UNLOCK();
     return RT_EOK;
 }
+
+void rt_wlan_mgnt_lock(void)
+{
+    MGNT_LOCK();
+}
+
+void rt_wlan_mgnt_unlock(void)
+{
+    MGNT_UNLOCK();
+}
+
+int rt_wlan_prot_ready_event(struct rt_wlan_device *wlan, struct rt_wlan_buff *buff)
+{
+    rt_base_t level;
+    void *user_parameter;
+    rt_wlan_event_handler handler = RT_NULL;
+
+    if ((wlan == RT_NULL) || (_sta_mgnt.device != wlan) ||
+            (!(_sta_mgnt.state & RT_WLAN_STATE_CONNECT)))
+    {
+        return -1;
+    }
+    if (_sta_mgnt.state & RT_WLAN_STATE_READY)
+    {
+        return 0;
+    }
+    level = rt_hw_interrupt_disable();
+    _sta_mgnt.state |= RT_WLAN_STATE_READY;
+    handler = event_tab[RT_WLAN_EVT_READY].handler;
+    user_parameter = event_tab[RT_WLAN_EVT_READY].parameter;
+    rt_hw_interrupt_enable(level);
+    if (handler)
+    {
+        handler(RT_WLAN_EVT_READY, buff, user_parameter);
+    }
+    return 0;
+}
+
+int rt_wlan_init(void)
+{
+    static rt_int8_t _init_flag = 0;
+
+    /* Execute only once */
+    if (_init_flag == 0)
+    {
+        rt_memset(&_sta_mgnt, 0, sizeof(struct rt_wlan_mgnt_des));
+        rt_memset(&_ap_mgnt, 0, sizeof(struct rt_wlan_mgnt_des));
+        rt_memset(&scan_result, 0, sizeof(struct rt_wlan_scan_result));
+        rt_memset(&sta_info, 0, sizeof(struct rt_wlan_sta_des));
+        rt_mutex_init(&mgnt_mutex, "mgnt", RT_IPC_FLAG_FIFO);
+        rt_mutex_init(&scan_result_mutex, "scan", RT_IPC_FLAG_FIFO);
+        rt_mutex_init(&sta_info_mutex, "sta", RT_IPC_FLAG_FIFO);
+        rt_mutex_init(&complete_mutex, "complete", RT_IPC_FLAG_FIFO);
+        rt_timer_init(&reconnect_time, "wifi_tim", rt_wlan_cyclic_check, RT_NULL, DISCONNECT_RESPONSE_TICK, RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER);
+        rt_timer_start(&reconnect_time);
+        _init_flag = 1;
+    }
+    return 0;
+}
+INIT_PREV_EXPORT(rt_wlan_init);

+ 138 - 22
components/drivers/wlan/wlan_mgnt.h

@@ -1,34 +1,150 @@
 /*
- *  RT-Thread Wi-Fi Device
+ * Copyright (c) 2006-2018, RT-Thread Development Team
  *
- * COPYRIGHT (C) 2014 - 2018, Shanghai Real-Thread Technology Co., Ltd
- *
- *  This file is part of RT-Thread (http://www.rt-thread.org)
- *
- *  All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * SPDX-License-Identifier: Apache-2.0
  *
  * Change Logs:
  * Date           Author       Notes
- * 2018-02-27     EvalZero     the first verion
+ * 2018-08-06     tyx          the first version
  */
 
 #ifndef __WLAN_MGNT_H__
 #define __WLAN_MGNT_H__
 
-int rt_wlan_mgnt_attach(struct rt_wlan_device *device, void *user_data);
+#include <wlan_dev.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef RT_WLAN_SCAN_WAIT_MS
+#define RT_WLAN_SCAN_WAIT_MS       (10 * 1000)
+#endif
+
+#ifndef RT_WLAN_SCAN_CACHE_NUM
+#define RT_WLAN_SCAN_CACHE_NUM     (50)
+#endif
+
+#ifndef RT_WLAN_CONNECT_WAIT_MS
+#define RT_WLAN_CONNECT_WAIT_MS    (10 * 1000)
+#endif
+
+#ifndef RT_WLAN_START_AP_WAIT_MS
+#define RT_WLAN_START_AP_WAIT_MS    (10 * 1000)
+#endif
+
+#ifndef RT_WLAN_EBOX_NUM
+#define RT_WLAN_EBOX_NUM           (10)
+#endif
+
+/*state fot station*/
+#define RT_WLAN_STATE_CONNECT     (1UL << 0)
+#define RT_WLAN_STATE_CONNECTING  (1UL << 1)
+#define RT_WLAN_STATE_READY       (1UL << 2)
+#define RT_WLAN_STATE_POWERSAVE   (1UL << 3)
+
+/*flags fot station*/
+#define RT_WLAN_STATE_AUTOEN      (1UL << 0)
+
+/*state fot ap*/
+#define RT_WLAN_STATE_ACTIVE      (1UL << 0)
+
+typedef enum
+{
+    RT_WLAN_EVT_READY = 0,              /* connect and prot is ok, You can send data*/
+    RT_WLAN_EVT_SCAN_DONE,              /* Scan a info */
+    RT_WLAN_EVT_SCAN_REPORT,            /* Scan end */
+    RT_WLAN_EVT_STA_CONNECTED,          /* connect success */
+    RT_WLAN_EVT_STA_CONNECTED_FAIL,     /* connection failed */
+    RT_WLAN_EVT_STA_DISCONNECTED,       /* disconnect */
+    RT_WLAN_EVT_AP_START,               /* AP start */
+    RT_WLAN_EVT_AP_STOP,                /* AP stop */
+    RT_WLAN_EVT_AP_ASSOCIATED,          /* sta associated */
+    RT_WLAN_EVT_AP_DISASSOCIATED,       /* sta disassociated */
+    RT_WLAN_EVT_MAX
+} rt_wlan_event_t;
+
+typedef void (*rt_wlan_event_handler)(int event, struct rt_wlan_buff *buff, void *parameter);
+
+struct rt_wlan_scan_result
+{
+    rt_int32_t num;
+    struct rt_wlan_info *info;
+};
+
+/*
+ * wifi init interface
+ */
+int rt_wlan_init(void);
+rt_err_t rt_wlan_set_mode(const char *dev_name, rt_wlan_mode_t mode);
+rt_wlan_mode_t rt_wlan_get_mode(const char *dev_name);
+
+/*
+ * wifi station mode interface
+ */
+rt_err_t rt_wlan_connect(const char *ssid, const char *password);
+rt_err_t rt_wlan_connect_adv(struct rt_wlan_info *info, const char *password);
+rt_err_t rt_wlan_disconnect(void);
+rt_bool_t rt_wlan_is_connected(void);
+rt_bool_t rt_wlan_is_ready(void);
+rt_err_t rt_wlan_set_mac(rt_uint8_t *mac);
+rt_err_t rt_wlan_get_mac(rt_uint8_t *mac);
+rt_err_t rt_wlan_get_info(struct rt_wlan_info *info);
+int rt_wlan_get_rssi(void);
+
+/*
+ * wifi ap mode interface
+ */
+rt_err_t rt_wlan_start_ap(const char *ssid, const char *password);
+rt_err_t rt_wlan_start_ap_adv(struct rt_wlan_info *info, const char *password);
+int rt_wlan_ap_is_active(void);
+rt_err_t rt_wlan_ap_stop(void);
+rt_err_t rt_wlan_ap_get_info(struct rt_wlan_info *info);
+int rt_wlan_ap_get_sta_num(void);
+int rt_wlan_ap_get_sta_info(struct rt_wlan_info *info, int num);
+rt_err_t rt_wlan_ap_deauth_sta(rt_uint8_t *mac);
+rt_err_t rt_wlan_ap_set_country(rt_country_code_t country_code);
+rt_country_code_t rt_wlan_ap_get_country(void);
+
+/*
+ * wifi scan interface
+ */
+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);
+
+/*
+ * wifi auto connect interface
+ */
+void rt_wlan_config_autoreconnect(rt_bool_t enable);
+rt_bool_t rt_wlan_get_autoreconnect_mode(void);
+
+/*
+ * wifi power management interface
+ */
+rt_err_t rt_wlan_set_powersave(int level);
+int rt_wlan_get_powersave(void);
+
+/*
+ * wifi event management interface
+ */
+rt_err_t rt_wlan_register_event_handler(rt_wlan_event_t event, rt_wlan_event_handler handler, void *parameter);
+rt_err_t rt_wlan_unregister_event_handler(rt_wlan_event_t event);
+
+/*
+ * wifi management lock interface
+ */
+void rt_wlan_mgnt_lock(void);
+void rt_wlan_mgnt_unlock(void);
+
+#ifdef __cplusplus
+}
+#endif
 
 #endif

+ 364 - 0
components/drivers/wlan/wlan_prot.c

@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-14     tyx          the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <wlan_dev.h>
+#include <wlan_prot.h>
+
+#define DBG_ENABLE
+#ifdef RT_WLAN_PROT_DEBUG
+#define DBG_LEVEL DBG_LOG
+#else
+#define DBG_LEVEL DBG_INFO
+#endif
+#define DBG_SECTION_NAME  "WLAN.prot"
+#define DBG_COLOR
+#include <rtdbg.h>
+
+#if RT_WLAN_PROT_NAME_LEN < 4
+#error "The name is too short"
+#endif
+
+struct rt_wlan_prot_event_des
+{
+    rt_wlan_prot_event_handler handler;
+    struct rt_wlan_prot *prot;
+};
+
+static struct rt_wlan_prot *_prot[RT_WLAN_PROT_MAX];
+
+static struct rt_wlan_prot_event_des prot_event_tab[RT_WLAN_PROT_EVT_MAX][RT_WLAN_PROT_MAX];
+
+static void rt_wlan_prot_event_handle(struct rt_wlan_device *wlan, rt_wlan_dev_event_t event, struct rt_wlan_buff *buff, void *parameter)
+{
+    int i;
+    struct rt_wlan_prot *wlan_prot;
+    struct rt_wlan_prot *prot;
+    rt_wlan_prot_event_handler handler;
+    rt_wlan_prot_event_t prot_event;
+
+    LOG_D("F:%s L:%d event:%d", __FUNCTION__, __LINE__, event);
+
+    wlan_prot = wlan->prot;
+    handler = RT_NULL;
+    prot = RT_NULL;
+    switch (event)
+    {
+    case RT_WLAN_DEV_EVT_INIT_DONE:
+    {
+        LOG_D("L%d event: INIT_DONE", __LINE__);
+        prot_event = RT_WLAN_PROT_EVT_INIT_DONE;
+        break;
+    }
+    case RT_WLAN_DEV_EVT_CONNECT:
+    {
+        LOG_D("L%d event: CONNECT", __LINE__);
+        prot_event = RT_WLAN_PROT_EVT_CONNECT;
+        break;
+    }
+    case RT_WLAN_DEV_EVT_DISCONNECT:
+    {
+        LOG_D("L%d event: DISCONNECT", __LINE__);
+        prot_event = RT_WLAN_PROT_EVT_DISCONNECT;
+        break;
+    }
+    case RT_WLAN_DEV_EVT_AP_START:
+    {
+        LOG_D("L%d event: AP_START", __LINE__);
+        prot_event = RT_WLAN_PROT_EVT_AP_START;
+        break;
+    }
+    case RT_WLAN_DEV_EVT_AP_STOP:
+    {
+        LOG_D("L%d event: AP_STOP", __LINE__);
+        prot_event = RT_WLAN_PROT_EVT_AP_STOP;
+        break;
+    }
+    case RT_WLAN_DEV_EVT_AP_ASSOCIATED:
+    {
+        LOG_D("L%d event: AP_ASSOCIATED", __LINE__);
+        prot_event = RT_WLAN_PROT_EVT_AP_ASSOCIATED;
+        break;
+    }
+    case RT_WLAN_DEV_EVT_AP_DISASSOCIATED:
+    {
+        LOG_D("L%d event: AP_DISASSOCIATED", __LINE__);
+        prot_event = RT_WLAN_PROT_EVT_AP_DISASSOCIATED;
+        break;
+    }
+    default:
+    {
+        return;
+    }
+    }
+    for (i = 0; i < RT_WLAN_PROT_MAX; i++)
+    {
+        if ((prot_event_tab[prot_event][i].handler != RT_NULL) &&
+                (prot_event_tab[prot_event][i].prot->id == wlan_prot->id))
+        {
+            handler = prot_event_tab[prot_event][i].handler;
+            prot = prot_event_tab[prot_event][i].prot;
+            break;
+        }
+    }
+
+    if (handler != RT_NULL)
+    {
+        handler(prot, wlan, prot_event);
+    }
+}
+
+static struct rt_wlan_device *rt_wlan_prot_find_by_name(const char *name)
+{
+    rt_device_t device;
+
+    if (name == RT_NULL)
+    {
+        LOG_E("F:%s L:%d Parameter Wrongful", __FUNCTION__, __LINE__);
+        return RT_NULL;
+    }
+    device = rt_device_find(name);
+    if (device == RT_NULL)
+    {
+        LOG_E("F:%s L:%d not find wlan dev!! name:%s", __FUNCTION__, __LINE__, name);
+        return RT_NULL;
+    }
+    return (struct rt_wlan_device *)device;
+}
+
+rt_err_t rt_wlan_prot_attach(const char *dev_name, const char *prot_name)
+{
+    struct rt_wlan_device *wlan;
+
+    wlan = rt_wlan_prot_find_by_name(dev_name);
+    if (wlan == RT_NULL)
+    {
+        return -RT_ERROR;
+    }
+    return rt_wlan_prot_attach_dev(wlan, prot_name);
+}
+
+rt_err_t rt_wlan_prot_detach(const char *name)
+{
+    struct rt_wlan_device *wlan;
+
+    wlan = rt_wlan_prot_find_by_name(name);
+    if (wlan == RT_NULL)
+    {
+        return -RT_ERROR;
+    }
+    return rt_wlan_prot_detach_dev(wlan);
+}
+
+rt_err_t rt_wlan_prot_attach_dev(struct rt_wlan_device *wlan, const char *prot_name)
+{
+    int i = 0;
+    struct rt_wlan_prot *prot = wlan->prot;
+    rt_wlan_dev_event_t event;
+
+    if (wlan == RT_NULL)
+    {
+        LOG_E("F:%s L:%d wlan is null", __FUNCTION__, __LINE__);
+        return -RT_ERROR;
+    }
+
+    if (prot != RT_NULL &&
+            (rt_strcmp(prot->name, prot_name) == 0))
+    {
+        LOG_D("prot is register");
+        return RT_EOK;
+    }
+
+    /* if prot not NULL */
+    if (prot != RT_NULL)
+        rt_wlan_prot_detach_dev(wlan);
+
+#ifdef RT_WLAN_PROT_LWIP_PBUF_FORCE
+    if (rt_strcmp(RT_WLAN_PROT_LWIP, prot_name) != 0)
+    {
+        return -RT_ERROR;
+    }
+#endif
+    /* find prot */
+    for (i = 0; i < RT_WLAN_PROT_MAX; i++)
+    {
+        if ((_prot[i] != RT_NULL) && (rt_strcmp(_prot[i]->name, prot_name) == 0))
+        {
+            /* attach prot */
+            wlan->prot = _prot[i]->ops->dev_reg_callback(_prot[i], wlan);
+            break;
+        }
+    }
+
+    if (i >= RT_WLAN_PROT_MAX)
+    {
+        LOG_E("F:%s L:%d not find wlan protocol", __FUNCTION__, __LINE__);
+        return -RT_ERROR;
+    }
+
+    for (event = RT_WLAN_DEV_EVT_INIT_DONE; event < RT_WLAN_DEV_EVT_MAX; event ++)
+    {
+        if (rt_wlan_dev_register_event_handler(wlan, event, rt_wlan_prot_event_handle, RT_NULL) != RT_EOK)
+        {
+            LOG_E("prot register event filed:%d", event);
+        }
+    }
+
+    return RT_EOK;
+}
+
+rt_err_t rt_wlan_prot_detach_dev(struct rt_wlan_device *wlan)
+{
+    struct rt_wlan_prot *prot = wlan->prot;
+    rt_wlan_dev_event_t event;
+
+    if (prot == RT_NULL)
+        return RT_EOK;
+
+    for (event = RT_WLAN_DEV_EVT_INIT_DONE; event < RT_WLAN_DEV_EVT_MAX; event ++)
+    {
+        rt_wlan_dev_unregister_event_handler(wlan, event, rt_wlan_prot_event_handle);
+    }
+
+    /* detach prot */
+    prot->ops->dev_unreg_callback(prot, wlan);
+    wlan->prot = RT_NULL;
+
+    return RT_EOK;
+}
+
+rt_err_t rt_wlan_prot_regisetr(struct rt_wlan_prot *prot)
+{
+    int i;
+    rt_uint32_t id;
+    static rt_uint8_t num;
+
+    /* Parameter checking */
+    if ((prot == RT_NULL) ||
+            (prot->ops->prot_recv == RT_NULL) ||
+            (prot->ops->dev_reg_callback == RT_NULL))
+    {
+        LOG_E("F:%s L:%d Parameter Wrongful", __FUNCTION__, __LINE__);
+        return -RT_EINVAL;
+    }
+
+    /* save prot */
+    for (i = 0; i < RT_WLAN_PROT_MAX; i++)
+    {
+        if (_prot[i] == RT_NULL)
+        {
+            id = (RT_LWAN_ID_PREFIX << 16) | num;
+            prot->id = id;
+            _prot[i] = prot;
+            num ++;
+            break;
+        }
+        else if (rt_strcmp(_prot[i]->name, prot->name) == 0)
+        {
+            break;
+        }
+    }
+
+    /* is full */
+    if (i >= RT_WLAN_PROT_MAX)
+    {
+        LOG_E("F:%s L:%d Space full", __FUNCTION__, __LINE__);
+        return -RT_ERROR;
+    }
+
+    return RT_EOK;
+}
+
+rt_err_t rt_wlan_prot_event_register(struct rt_wlan_prot *prot, rt_wlan_prot_event_t event, rt_wlan_prot_event_handler handler)
+{
+    int i;
+
+    if ((prot == RT_NULL) || (handler == RT_NULL))
+    {
+        return -RT_EINVAL;
+    }
+
+    for (i = 0; i < RT_WLAN_PROT_MAX; i++)
+    {
+        if (prot_event_tab[event][i].handler == RT_NULL)
+        {
+            prot_event_tab[event][i].handler = handler;
+            prot_event_tab[event][i].prot = prot;
+            return RT_EOK;
+        }
+    }
+
+    return -RT_ERROR;
+}
+
+rt_err_t rt_wlan_prot_event_unregister(struct rt_wlan_prot *prot, rt_wlan_prot_event_t event)
+{
+    int i;
+
+    if (prot == RT_NULL)
+    {
+        return -RT_EINVAL;
+    }
+
+    for (i = 0; i < RT_WLAN_PROT_MAX; i++)
+    {
+        if ((prot_event_tab[event][i].handler != RT_NULL) &&
+                (prot_event_tab[event][i].prot == prot))
+        {
+            rt_memset(&prot_event_tab[event][i], 0, sizeof(struct rt_wlan_prot_event_des));
+            return RT_EOK;
+        }
+    }
+
+    return -RT_ERROR;
+}
+
+rt_err_t rt_wlan_prot_transfer_dev(struct rt_wlan_device *wlan, void *buff, int len)
+{
+    if (wlan->ops->wlan_send != RT_NULL)
+    {
+        return wlan->ops->wlan_send(wlan, buff, len);
+    }
+    return -RT_ERROR;
+}
+
+rt_err_t rt_wlan_dev_transfer_prot(struct rt_wlan_device *wlan, void *buff, int len)
+{
+    struct rt_wlan_prot *prot = wlan->prot;
+
+    if (prot != RT_NULL)
+    {
+        return prot->ops->prot_recv(wlan, buff, len);
+    }
+    return -RT_ERROR;
+}
+
+extern int rt_wlan_prot_ready_event(struct rt_wlan_device *wlan, struct rt_wlan_buff *buff);
+int rt_wlan_prot_ready(struct rt_wlan_device *wlan, struct rt_wlan_buff *buff)
+{
+    return rt_wlan_prot_ready_event(wlan, buff);
+}
+
+void rt_wlan_prot_dump(void)
+{
+    int i;
+
+    rt_kprintf("  name       id \n");
+    rt_kprintf("--------  --------\n");
+    for (i = 0; i < RT_WLAN_PROT_MAX; i++)
+    {
+        if (_prot[i] != RT_NULL)
+        {
+            rt_kprintf("%-8.8s  ", _prot[i]->name);
+            rt_kprintf("%08x\n", _prot[i]->id);
+        }
+    }
+}

+ 85 - 0
components/drivers/wlan/wlan_prot.h

@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-14     tyx          the first version
+ */
+
+#ifndef __WLAN_PROT_H__
+#define __WLAN_PROT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef RT_WLAN_PROT_NAME_LEN
+#define RT_WLAN_PROT_NAME_LEN  (8)
+#endif
+
+#ifndef RT_WLAN_PROT_MAX
+#define RT_WLAN_PROT_MAX       (1)
+#endif
+
+#define RT_LWAN_ID_PREFIX      (0x5054)
+
+#define RT_WLAN_PROT_LWIP  ("lwip")
+
+typedef enum
+{
+    RT_WLAN_PROT_EVT_INIT_DONE = 0,
+    RT_WLAN_PROT_EVT_CONNECT,
+    RT_WLAN_PROT_EVT_DISCONNECT,
+    RT_WLAN_PROT_EVT_AP_START,
+    RT_WLAN_PROT_EVT_AP_STOP,
+    RT_WLAN_PROT_EVT_AP_ASSOCIATED,
+    RT_WLAN_PROT_EVT_AP_DISASSOCIATED,
+    RT_WLAN_PROT_EVT_MAX,
+} rt_wlan_prot_event_t;
+
+struct rt_wlan_prot;
+struct rt_wlan_prot_ops
+{
+    rt_err_t (*prot_recv)(struct rt_wlan_device *wlan, void *buff, int len);
+    struct rt_wlan_prot *(*dev_reg_callback)(struct rt_wlan_prot *prot, struct rt_wlan_device *wlan);
+    void (*dev_unreg_callback)(struct rt_wlan_prot *prot, struct rt_wlan_device *wlan);
+};
+
+struct rt_wlan_prot
+{
+    char name[RT_WLAN_PROT_NAME_LEN];
+    rt_uint32_t id;
+    const struct rt_wlan_prot_ops *ops;
+};
+
+typedef void (*rt_wlan_prot_event_handler)(struct rt_wlan_prot *port, struct rt_wlan_device *wlan, int event);
+
+rt_err_t rt_wlan_prot_attach(const char *dev_name, const char *prot_name);
+
+rt_err_t rt_wlan_prot_attach_dev(struct rt_wlan_device *wlan, const char *prot_name);
+
+rt_err_t rt_wlan_prot_detach(const char *dev_name);
+
+rt_err_t rt_wlan_prot_detach_dev(struct rt_wlan_device *wlan);
+
+rt_err_t rt_wlan_prot_regisetr(struct rt_wlan_prot *prot);
+
+rt_err_t rt_wlan_prot_transfer_dev(struct rt_wlan_device *wlan, void *buff, int len);
+
+rt_err_t rt_wlan_dev_transfer_prot(struct rt_wlan_device *wlan, void *buff, int len);
+
+rt_err_t rt_wlan_prot_event_register(struct rt_wlan_prot *prot, rt_wlan_prot_event_t event, rt_wlan_prot_event_handler handler);
+
+rt_err_t rt_wlan_prot_event_unregister(struct rt_wlan_prot *prot, rt_wlan_prot_event_t event);
+
+int rt_wlan_prot_ready(struct rt_wlan_device *wlan, struct rt_wlan_buff *buff);
+
+void rt_wlan_prot_dump(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 99 - 0
components/drivers/wlan/wlan_workqueue.c

@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-19     tyx          the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <wlan_workqueue.h>
+#include <ipc/workqueue.h>
+
+#define DBG_ENABLE
+#define DBG_LEVEL DBG_INFO
+#define DBG_SECTION_NAME  "WLAN.work"
+#define DBG_COLOR
+#include <rtdbg.h>
+
+struct rt_wlan_work
+{
+    struct rt_work work;
+    void (*fun)(void *parameter);
+    void *parameter;
+};
+
+static struct rt_workqueue *wlan_workqueue;
+
+static void rt_wlan_workqueue_fun(struct rt_work *work, void *work_data)
+{
+    struct rt_wlan_work *wlan_work = work_data;
+
+    wlan_work->fun(wlan_work->parameter);
+    rt_free(wlan_work);
+}
+
+struct rt_workqueue *rt_wlan_get_workqueue(void)
+{
+    return wlan_workqueue;
+}
+
+rt_err_t rt_wlan_workqueue_dowork(void (*func)(void *parameter), void *parameter)
+{
+    struct rt_wlan_work *wlan_work;
+    rt_err_t err = RT_EOK;
+
+    LOG_D("F:%s is run", __FUNCTION__);
+    if (func == RT_NULL)
+    {
+        LOG_E("F:%s L:%d func is null", __FUNCTION__, __LINE__);
+        return -RT_EINVAL;
+    }
+
+    if (wlan_workqueue == RT_NULL)
+    {
+        LOG_E("F:%s L:%d not init wlan work queue", __FUNCTION__, __LINE__);
+        return -RT_ERROR;
+    }
+
+    wlan_work = rt_malloc(sizeof(struct rt_wlan_work));
+    if (wlan_work == RT_NULL)
+    {
+        LOG_E("F:%s L:%d create work failed", __FUNCTION__, __LINE__);
+        return -RT_ENOMEM;
+    }
+    wlan_work->fun = func;
+    wlan_work->parameter = parameter;
+    rt_work_init(&wlan_work->work, rt_wlan_workqueue_fun, wlan_work);
+    err = rt_workqueue_dowork(wlan_workqueue, &wlan_work->work);
+    if (err != RT_EOK)
+    {
+        LOG_E("F:%s L:%d do work failed", __FUNCTION__, __LINE__);
+        rt_free(wlan_work);
+        return err;
+    }
+    return err;
+}
+
+int rt_wlan_workqueue_init(void)
+{
+    static rt_int8_t _init_flag = 0;
+
+    if (_init_flag == 0)
+    {
+        wlan_workqueue = rt_workqueue_create(RT_WLAN_WORKQUEUE_THREAD_NAME, RT_WLAN_WORKQUEUE_THREAD_SIZE,
+                                             RT_WLAN_WORKQUEUE_THREAD_PRIO);
+        if (wlan_workqueue == RT_NULL)
+        {
+            LOG_E("F:%s L:%d wlan work queue create failed", __FUNCTION__, __LINE__);
+            return -1;
+        }
+        _init_flag = 1;
+        return 0;
+    }
+    return 0;
+}
+INIT_PREV_EXPORT(rt_wlan_workqueue_init);

+ 42 - 0
components/drivers/wlan/wlan_workqueue.h

@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-19     tyx          the first version
+ */
+
+#ifndef __WLAN_WORKQUEUE_H__
+#define __WLAN_WORKQUEUE_H__
+
+#include <ipc/workqueue.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef RT_WLAN_WORKQUEUE_THREAD_NAME
+#define RT_WLAN_WORKQUEUE_THREAD_NAME  ("wlan_job")
+#endif
+
+#ifndef RT_WLAN_WORKQUEUE_THREAD_SIZE
+#define RT_WLAN_WORKQUEUE_THREAD_SIZE  (2048)
+#endif
+
+#ifndef RT_WLAN_WORKQUEUE_THREAD_PRIO
+#define RT_WLAN_WORKQUEUE_THREAD_PRIO  (20)
+#endif
+
+int rt_wlan_workqueue_init(void);
+
+rt_err_t rt_wlan_workqueue_dowork(void (*func)(void *parameter), void *parameter);
+
+struct rt_workqueue *rt_wlan_get_workqueue(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif