提交 324bfc58 编写于 作者: 还_没_想_好's avatar 还_没_想_好

[DeviceDriver][wlan] add new wlan framework

上级 2c6c4a74
......@@ -194,31 +194,73 @@ 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 "Scan timeout time"
default 10000;
config RT_WLAN_CONNECT_WAIT_MS
int "connect timeout time"
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"
default n
config RT_WLAN_CFG_INFO_MAX
int "Maximum number of WiFi information automatically saved"
default 3
config WIFI_DEVICE_STA_NAME
string "the wifi device name for station"
default "w0"
config RT_WLAN_WORKQUEUE_THREAD_NAME
string "WiFi work queue thread name"
default "wlan_job"
config WIFI_DEVICE_AP_NAME
string "the wifi device name for ap"
default "ap"
endif
config RT_WLAN_WORKQUEUE_THREAD_SIZE
int "wifi work queue thread size"
default 2048
config RT_USING_AUDIO
bool "Using Audio device drivers"
default n
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
endif
endmenu
menu "Using USB"
config RT_USING_USB_HOST
......
/*
* 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
......@@ -117,6 +117,10 @@ extern "C" {
#include "drivers/rt_drv_pwm.h"
#endif
#ifdef RT_USING_WIFI
#include "drivers/wlan.h"
#endif
#ifdef __cplusplus
}
#endif
......
/*
* 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
#define DBG_LEVEL DBG_INFO
#define DBG_SECTION_NAME "WLAN.cfg"
#define DBG_COLOR
#include <rtdbg.h>
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;
};
#define WLAN_CFG_LOCK() (rt_mutex_take(&cfg_mutex, RT_WAITING_FOREVER))
#define WLAN_CFG_UNLOCK() (rt_mutex_release(&cfg_mutex))
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 (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 (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);
}
}
/*
* 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
#if RT_WLAN_CFG_INFO_MAX < 1
#error "The minimum configuration 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
/*
* 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;
#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"
#endif
#ifdef RT_USING_DFS
#include <dfs_posix.h>
#ifdef PKG_USING_CJSON
#include <cJSON_util.h>
#endif
int wifi_get_mode(void)
{
return network_mode;
}
#include <wlan_mgnt.h>
#include <wlan_cfg.h>
#include <wlan_prot.h>
int wifi_set_mode(int mode)
struct wifi_cmd_des
{
network_mode = mode;
return network_mode;
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 list_sta(int argc, char *argv[]);
static int wifi_disconnect(int argc, char *argv[]);
static int wifi_ap_stop(int argc, char *argv[]);
static int wifi_debug(int argc, char *argv[]);
/* just for debug */
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[]);
/* 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", list_sta},
{"disc", wifi_disconnect},
{"ap_stop", wifi_ap_stop},
{"smartconfig", RT_NULL},
{"-d", wifi_debug},
};
/* debug cmd table */
static const struct wifi_cmd_des debug_tab[] =
{
{"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},
};
static int wifi_help(int argc, char *argv[])
{
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");
rt_kprintf("wifi -d debug command\n");
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)
{
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
{
strncpy(wifi_key, pwd, sizeof(wifi_key));
wifi_key[sizeof(wifi_key) - 1] = '\0';
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 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)
/* 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;
}
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);
FINSH_FUNCTION_EXPORT_ALIAS(wifi_msh, __cmd_wifi, wifi command.);
/*
* 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
/*
* 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
#define DBG_LEVEL DBG_INFO
#define DBG_SECTION_NAME "WLAN.dev"
#define DBG_COLOR
#include <rtdbg.h>
#include "wlan_dev.h"
#include "wlan_cmd.h"
#ifndef RT_DEVICE
#define RT_DEVICE(__device) ((rt_device_t)__device)
#endif
#define NIOCTL_SADDR 0x02
#define WLAN_DEV_LOCK(_wlan) (rt_mutex_take(&(_wlan)->lock, RT_WAITING_FOREVER))
#define WLAN_DEV_UNLOCK(_wlan) (rt_mutex_release(&(_wlan)->lock))
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_init(struct rt_wlan_device *device, rt_wlan_mode_t mode)
{
if (info == RT_NULL) return ;
rt_err_t result = RT_EOK;
memset(info, 0x0, sizeof(struct rt_wlan_info));
info->mode = mode;
info->security = security;
if (ssid)
/* 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))
{
info->ssid = rt_malloc(strlen((char *)ssid) + 1);
if (info->ssid)
{
strncpy((char *)info->ssid, (char *)ssid, strlen((char *)ssid) + 1);
}
LOG_E("F:%s L:%d Parameter Wrongful device:0x%08x mode:%d", __FUNCTION__, __LINE__, device, mode);
return -RT_ERROR;
}
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_deinit(struct rt_wlan_info *info)
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->ssid)
rt_err_t result = RT_EOK;
struct rt_sta_info sta_info;
if (device == RT_NULL)
{
rt_free(info->ssid);
info->ssid = RT_NULL;
return -RT_EIO;
}
if (info == RT_NULL)
{
return -RT_ERROR;
}
if ((password_len > RT_WLAN_PASSWORD_MAX_LENGTH) ||
(info->ssid.len > RT_WLAN_SSID_MAX_LENGTH))
{
LOG_E("L:%d password or ssid is 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;
memset(info, 0x0, sizeof(struct rt_wlan_info));
result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_JOIN, &sta_info);
return result;
}
int rt_wlan_init(struct rt_wlan_device *device, rt_wlan_mode_t mode)
rt_err_t rt_wlan_dev_disconnect(struct rt_wlan_device *device)
{
int result;
rt_err_t result = RT_EOK;
if (device == RT_NULL) return 0;
if (device == RT_NULL)
{
return -RT_EIO;
}
result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_DISCONNECT, RT_NULL);
return result;
}
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 result = RT_EOK;
struct rt_ap_info ap_info;
if (device->info == RT_NULL)
if (device == RT_NULL)
{
struct rt_wlan_info *info;
char *ssid;
return -RT_EIO;
}
if (info == RT_NULL)
{
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 = 0;
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 = 0;
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 = 0;
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_enable_powersave(struct rt_wlan_device *device)
{
int result = 0;
if (device == RT_NULL) return -RT_EIO;
rt_err_t result = RT_EOK;
int enable = 1;
/* 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_POWERSAVE, &enable);
return result;
}
int rt_wlan_set_info(struct rt_wlan_device *device, struct rt_wlan_info *info)
rt_err_t rt_wlan_dev_disable_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;
rt_err_t result = RT_EOK;
int enable = 0;
return RT_EOK;
if (device == RT_NULL)
{
return -RT_EIO;
}
result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_POWERSAVE, &enable);
return result;
}
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)
{
return -RT_EIO;
}
if (event >= RT_WLAN_DEV_EVT_MAX)
{
return -RT_EINVAL;
}
if (device != RT_NULL)
level = rt_hw_interrupt_disable();
for (i = 0; i < RT_WLAN_DEV_EVENT_NUM; i++)
{
info = device->info;
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_exit_critical();
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_pormisc(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_pormisc(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_pormisc_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_pormisc_handler(struct rt_wlan_device *device, void *data, int len)
{
int result = 0;
rt_wlan_pormisc_callback_t callback;
if (device == RT_NULL)
{
return;
}
if (device == RT_NULL) return -RT_EIO;
callback = device->pormisc_callback;
result = rt_device_control(RT_DEVICE(device), WIFI_ENTER_POWERSAVE, (void *)&level);
if (callback != RT_NULL)
{
callback(device, data, len);
}
}
rt_err_t rt_wlan_dev_cfg_filter(struct rt_wlan_device *device, struct rt_wlan_filter *filter)
{
rt_err_t result = RT_EOK;
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;
if (device == RT_NULL)
{
return -RT_EIO;
}
device->handler[event] = RT_NULL;
result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_GET_CHANNEL, &channel);
if (result != RT_EOK)
{
return -1;
}
return RT_EOK;
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;
}
result = rt_device_control(RT_DEVICE(device), WIFI_SET_MONITOR_CALLBACK, (void *)callback);
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;
}
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);
}
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;
if (device == RT_NULL) return -RT_EIO;
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_POWERSAVE:
{
rt_bool_t enable = *((rt_bool_t *)args);
LOG_D("%s %d cmd[%d]:%s run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_POWERSAVE, "RT_WLAN_CMD_POWERSAVE");
if (wlan->ops->wlan_powersave)
wlan->ops->wlan_powersave(wlan, enable);
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;
}
wlan = rt_malloc(sizeof(struct rt_wlan_device));
if (wlan == RT_NULL)
{
LOG_E("F:%s L:%d", __FUNCTION__, __LINE__);
return RT_NULL;
}
rt_free(*scan_result);
*scan_result = RT_NULL;
scan_result = 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;
}
/*
* 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_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 +70,506 @@ 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
#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
/**
* 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);
char *ssid;
uint8_t bssid[6];
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;
#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;
};
/*
* Wi-Fi Information APIs
*/
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);
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;
};
/*
* Wi-Fi Manager APIs
*/
int rt_wlan_init(struct rt_wlan_device *device, rt_wlan_mode_t mode);
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;
};
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);
struct rt_scan_info
{
rt_wlan_ssid_t ssid;
rt_uint8_t bssid[6];
rt_int16_t channel_min;
rt_int16_t channel_max;
};
int rt_wlan_softap(struct rt_wlan_device *device, struct rt_wlan_info *info,
char *password);
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_powersave)(struct rt_wlan_device *wlan, rt_bool_t enable);
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);
};
rt_err_t rt_wlan_dev_init(struct rt_wlan_device *device, rt_wlan_mode_t mode);
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);
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]);
int rt_wlan_dev_get_rssi(struct rt_wlan_device *device);
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]);
/* 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);
rt_err_t rt_wlan_dev_enable_powersave(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);
rt_err_t rt_wlan_dev_disable_powersave(struct rt_wlan_device *device);
/* 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]);
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);
/* enter power save level */
int rt_wlan_enter_powersave(struct rt_wlan_device *device, int level);
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);
/* 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);
void rt_wlan_dev_indicate_event_handle(struct rt_wlan_device *device, rt_wlan_dev_event_t event, struct rt_wlan_buff *buff);
/* un-register the event handler */
int rt_wlan_unregister_event_handler(struct rt_wlan_device *device, rt_wlan_event_t event);
rt_err_t rt_wlan_dev_enter_pormisc(struct rt_wlan_device *device);
/* 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);
rt_err_t rt_wlan_dev_exit_pormisc(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);
rt_err_t rt_wlan_dev_set_pormisc_callback(struct rt_wlan_device *device, rt_wlan_pormisc_callback_t callback);
/* set callback function for monitor mode*/
int rt_wlan_set_monitor_callback(struct rt_wlan_device *device, rt_wlan_monitor_callback_t callback);
void rt_wlan_dev_pormisc_handler(struct rt_wlan_device *device, void *data, int len);
/* Set the monitor channel */
int rt_wlan_set_channel(struct rt_wlan_device *device, int channel);
rt_err_t rt_wlan_dev_cfg_filter(struct rt_wlan_device *device, struct rt_wlan_filter *filter);
void rt_wlan_release_scan_result(struct rt_wlan_scan_result **scan_result);
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);
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);
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);
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);
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);
#ifdef __cplusplus
}
#endif
#endif
/*
* 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
#define DBG_LEVEL DBG_INFO
#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
/*
* 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>
#define DBG_ENABLE
#define DBG_LEVEL DBG_INFO
#define DBG_SECTION_NAME "WLAN.mgnt"
#define DBG_COLOR
#include <rtdbg.h>
#include "wlan_dev.h"
#include "wlan_cmd.h"
#ifndef RT_WLAN_DEVICE
#define RT_WLAN_DEVICE(__device) ((struct rt_wlan_device *)__device)
#endif
#define WLAN_MGNT_DEBUG 1
#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__)
#if WLAN_MGNT_DEBUG
#define WLAN_MGNT_DBG(...) rt_kprintf("[WLAN_MGNT]"),rt_kprintf(__VA_ARGS__)
#else
#define WLAN_MGNT_DBG(...)
#endif
#define STA_DEVICE() (_sta_mgnt.device)
#define AP_DEVICE() (_ap_mgnt.device)
#ifndef WIFI_DEVICE_STA_NAME
#define WIFI_DEVICE_STA_NAME "w0"
#endif
#ifndef WIFI_DEVICE_AP_NAME
#define WIFI_DEVICE_AP_NAME "ap"
#endif
#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)
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 rt_mailbox_t event_box;
static struct rt_timer reconnect_time;
rt_inline int _sta_is_null(void)
{
if (_sta_mgnt.device == RT_NULL)
{
return 1;
}
return 0;
}
static void wlan_mgnt_init_done_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 init done event callback \n");
if (_ap_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 rt_bool_t _is_do_connect(void)
{
WLAN_MGNT_DBG("wlan link up 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_link_down_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 link down event callback \n");
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("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 void wlan_mgnt_sta_connect_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data)
static rt_err_t rt_wlan_scan_result_cache(struct rt_wlan_info *info, int timeout)
{
WLAN_MGNT_DBG("wlan sta connect event callback \n");
struct netif *netif = device->parent.netif;
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;
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;
netifapi_netif_set_up(netif);
netifapi_netif_set_link_up(netif);
#ifdef RT_LWIP_DHCP
/* start DHCP */
dhcp_start(netif);
/* 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(void)
{
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(200));
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_kprintf("zha guo zha guo zha guo\n");
sta_info.num = 0;
sta_info.node = RT_NULL;
return err;
}
static void wlan_mgnt_sta_disconnect_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data)
static void rt_wlan_auto_connect_run(struct rt_work *work, void *parameter)
{
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);
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:
MGNT_UNLOCK();
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;
}
case RT_WLAN_DEV_EVT_AP_ASSOCIATED:
{
/* save sta info */
if (msg->len > 0)
{
rt_wlan_sta_info_add(msg->buff, RT_WAITING_FOREVER);
}
break;
}
case RT_WLAN_DEV_EVT_AP_DISASSOCIATED:
{
/* delete sta info */
if (msg->len > 0)
{
rt_wlan_sta_info_del(msg->buff, RT_WAITING_FOREVER);
}
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();
if (err != RT_NULL)
{
RT_WLAN_LOG_W("AP_STOP event handle fail");
rt_wlan_send_msg(event, RT_NULL, 0);
}
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, 200);
if (err != RT_EOK)
{
RT_WLAN_LOG_W("AP_ASSOCIATED event handle fail");
rt_wlan_send_msg(event, user_buff.data, sizeof(struct rt_wlan_info));
}
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, 200);
if (err != RT_EOK)
{
RT_WLAN_LOG_W("AP_DISASSOCIATED event handle fail");
rt_wlan_send_msg(event, user_buff.data, sizeof(struct rt_wlan_info));
}
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();
/* 取出用户回调 */
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 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)
{
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;
}
static void wlan_mgnt_ap_start_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data)
rt_err_t rt_wlan_disconnect(void)
{
WLAN_MGNT_DBG("wlan ap start event callback \n");
netifapi_netif_set_up(device->parent.netif);
netifapi_netif_set_link_up(device->parent.netif);
rt_err_t err;
struct rt_wlan_complete_des *complete;
rt_uint32_t recved = 0, set = 0;
wifi_softap_setup_netif(device->parent.netif);
/* 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;
}
int rt_wlan_is_connected(void)
{
int _connect = 0;
if (_sta_is_null())
{
return 0;
}
_connect = _sta_mgnt.state & RT_WLAN_STATE_CONNECT ? 1 : 0;
RT_WLAN_LOG_D("%s is run : %s", __FUNCTION__, _connect ? "connect" : "disconnect");
return _connect;
}
int rt_wlan_is_ready(void)
{
int _ready = 0;
if (_sta_is_null())
{
return 0;
}
_ready = _sta_mgnt.state & RT_WLAN_STATE_READY ? 1 : 0;
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__);
static void wlan_mgnt_ap_stop_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data)
rt_enter_critical();
*info = _sta_mgnt.info;
rt_exit_critical();
return RT_EOK;
}
int rt_wlan_get_rssi(void)
{
WLAN_MGNT_DBG("wlan ap stop event callback \n");
int rssi = 0;
if (_sta_is_null())
{
return -RT_EIO;
}
netifapi_netif_set_down(device->parent.netif);
netifapi_netif_set_link_down(device->parent.netif);
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;
}
static void wlan_mgnt_ap_associate_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data)
rt_err_t rt_wlan_start_ap(const char *ssid, const char *password)
{
WLAN_MGNT_DBG("wlan ap associate event callback \n");
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;
}
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_start_ap_adv(struct rt_wlan_info *info, const char *password)
{
WLAN_MGNT_DBG("wlan ap disassociate event callback \n");
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;
}
static void wlan_mgnt_scan_done_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data)
int rt_wlan_ap_is_active(void)
{
WLAN_MGNT_DBG("wlan scan done event callback \n");
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;
}
int rt_wlan_mgnt_attach(struct rt_wlan_device *device, void *user_data)
rt_err_t rt_wlan_ap_stop(void)
{
RT_ASSERT(device != RT_NULL);
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__);
/* 调用dev层接口 */
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_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);
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__);
/* 返回暂存的ap info */
*info = _ap_mgnt.info;
return RT_EOK;
}
/* 获得sta连接数量 */
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;
}
/* 获得sta信息 */
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();
/* 找出 num 与 sta_info.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;
}
/* 踢掉某个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();
/* 重缓存中查询有没有这个sta */
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();
/* 没有找个这个sta,退出 */
if (find_flag != RT_TRUE)
{
RT_WLAN_LOG_E("Not find mac addr");
MGNT_UNLOCK();
return -RT_ERROR;
}
/* 调用dev层接口,提到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;
}
int rt_wlan_scan_get_info(struct rt_wlan_info *info, int num)
{
int _num = 0;
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;
}
void rt_wlan_scan_result_clean(void)
{
MGNT_LOCK();
SRESULT_LOCK();
/* 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();
}
int rt_wlan_scan_find_cache(struct rt_wlan_info *info, struct rt_wlan_info *out_info, int num)
{
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;
}
rt_err_t rt_wlan_enable_powersave(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_enable_powersave(STA_DEVICE());
MGNT_UNLOCK();
return err;
}
rt_err_t rt_wlan_disable_powersave(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_disable_powersave(STA_DEVICE());
MGNT_UNLOCK();
return err;
}
rt_err_t rt_wlan_register_event_handler(rt_wlan_event_t event, rt_wlan_event_handler handler, void *parameter)
{
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_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);
/* create event */
event_box = rt_mb_create("wlan", RT_WLAN_EBOX_NUM, RT_IPC_FLAG_FIFO);
if (event_box == RT_NULL)
RT_ASSERT(event_box != RT_NULL);
_init_flag = 1;
}
return 0;
}
INIT_PREV_EXPORT(rt_wlan_init);
/*
* 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
#if RT_WLAN_EBOX_NUM < 1
#error "event box num Too little"
#endif
/*state fot station*/
#define RT_WLAN_STATE_CONNECT (0x1 << 0)
#define RT_WLAN_STATE_CONNECTING (0x1 << 1)
#define RT_WLAN_STATE_READY (0x1 << 2)
#define RT_WLAN_STATE_POWERSAVE (0x1 << 3)
/*flags fot station*/
#define RT_WLAN_STATE_AUTOEN (0x1 << 0)
/*state fot ap*/
#define RT_WLAN_STATE_ACTIVE (0x1 << 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);
int rt_wlan_is_connected(void);
int 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_enable_powersave(void);
rt_err_t rt_wlan_disable_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
/*
* 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
#define DBG_LEVEL DBG_INFO
#define DBG_SECTION_NAME "WLAN.prot"
#define DBG_COLOR
#include <rtdbg.h>
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);
}
}
}
/*
* 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)
#if RT_WLAN_PROT_NAME_LEN < 4
#error "The name is too short"
#endif
#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
/*
* 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);
/*
* 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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册