diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig index e2d290032b..c0e4f3e87a 100755 --- a/components/drivers/Kconfig +++ b/components/drivers/Kconfig @@ -194,32 +194,74 @@ config RT_USING_WDT bool "Using Watch Dog device drivers" default n -config RT_USING_WIFI - bool "Using Wi-Fi network" - default n - - if RT_USING_WIFI - config RT_USING_WLAN_STA - bool "Using station mode" - default y - - config RT_USING_WLAN_AP - bool "Using ap mode" - default n - - config WIFI_DEVICE_STA_NAME - string "the wifi device name for station" - default "w0" - - config WIFI_DEVICE_AP_NAME - string "the wifi device name for ap" - default "ap" - endif - 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_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_WLAN_CFG_INFO_MAX + int "Maximum number of WiFi information automatically saved" + default 3 + + config RT_WLAN_WORKQUEUE_THREAD_NAME + string "WiFi work queue thread name" + default "wlan_job" + + config RT_WLAN_WORKQUEUE_THREAD_SIZE + int "wifi work queue thread size" + default 2048 + + config RT_WLAN_WORKQUEUE_THREAD_PRIO + int "WiFi work queue thread priority" + default 22 + + config RT_WLAN_DEV_EVENT_NUM + int "Maximum number of driver events" + default 2 + + config RT_WLAN_PROT_LWIP_PBUF_FORCE + bool "Forced use of PBUF transmission" + default n + endif +endmenu + menu "Using USB" config RT_USING_USB_HOST bool "Using USB host" diff --git a/components/drivers/include/drivers/wlan.h b/components/drivers/include/drivers/wlan.h new file mode 100644 index 0000000000..724e61da78 --- /dev/null +++ b/components/drivers/include/drivers/wlan.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-09-15 tyx the first version + */ + +#ifndef __WLAN_H__ +#define __WLAN_H__ + +#include +#include +#include +#include +#include +#include + +#endif diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index eb28714891..b7fec50b73 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -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 diff --git a/components/drivers/wlan/wlan_cfg.c b/components/drivers/wlan/wlan_cfg.c new file mode 100644 index 0000000000..b0cc88be08 --- /dev/null +++ b/components/drivers/wlan/wlan_cfg.c @@ -0,0 +1,455 @@ +/* + * 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 +#include + +#define DBG_ENABLE +#define DBG_LEVEL DBG_INFO +#define DBG_SECTION_NAME "WLAN.cfg" +#define DBG_COLOR +#include + +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); + } +} diff --git a/components/drivers/wlan/wlan_cfg.h b/components/drivers/wlan/wlan_cfg.h new file mode 100644 index 0000000000..4527043c39 --- /dev/null +++ b/components/drivers/wlan/wlan_cfg.h @@ -0,0 +1,71 @@ +/* + * 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 + +#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 diff --git a/components/drivers/wlan/wlan_cmd.c b/components/drivers/wlan/wlan_cmd.c index eda628a357..e316a2c452 100644 --- a/components/drivers/wlan/wlan_cmd.c +++ b/components/drivers/wlan/wlan_cmd.c @@ -1,527 +1,554 @@ /* - * 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 -#include +#include +#include +#include -#include - -#include -#include "wlan_cmd.h" - -#ifdef LWIP_USING_DHCPD -#include -#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 -#ifdef PKG_USING_CJSON -#include -#endif - -int wifi_get_mode(void) +struct wifi_cmd_des { - return network_mode; -} + const char *cmd; + int (*fun)(int argc, char *argv[]); +}; -int wifi_set_mode(int mode) +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[] = { - network_mode = mode; + {"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}, +}; - return network_mode; -} - -int wifi_set_setting(const char *ssid, const char *pwd) +/* debug cmd table */ +static const struct wifi_cmd_des debug_tab[] = { - if (!ssid) return -1; - - strncpy(wifi_ssid, ssid, sizeof(wifi_ssid)); - wifi_ssid[sizeof(wifi_ssid) - 1] = '\0'; - - if (pwd) - { - strncpy(wifi_key, pwd, sizeof(wifi_key)); - wifi_key[sizeof(wifi_key) - 1] = '\0'; - } - else wifi_key[0] = '\0'; + {"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; } -#ifdef PKG_USING_CJSON -int wifi_read_cfg(const char *filename) +static int wifi_status(int argc, char *argv[]) { - int fd; - cJSON *json = RT_NULL; + int rssi; + struct rt_wlan_info info; - fd = open(filename, O_RDONLY, 0); - if (fd < 0) + if (argc > 2) + return -1; + + 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 + { + rt_kprintf("wifi disconnected!\n"); + } + + 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; +} + +static int wifi_scan(int argc, char *argv[]) +{ + struct rt_wlan_scan_result *scan_result = RT_NULL; + + if (argc > 2) + return -1; + + /* scan ap info */ + scan_result = rt_wlan_scan_sync(); + if (scan_result) + { + int index, num; + char *security; + + num = scan_result->num; + rt_kprintf(" SSID MAC security rssi chn Mbps\n"); + rt_kprintf("------------------------------- ----------------- -------------- ---- --- ----\n"); + for (index = 0; index < num; index ++) + { + 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) + { + 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); + } + rt_wlan_scan_result_clean(); + } + else + { + rt_kprintf("wifi scan result is null\n"); + } + return 0; +} + +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 (argc == 2) + { + /* get info to connect */ + if (rt_wlan_cfg_read_index(&cfg_info, 0) == 1) + { + ssid = (char *)(&cfg_info.info.ssid.val[0]); + if (cfg_info.key.len) + key = (char *)(&cfg_info.key.val[0]); + } + else + { + rt_kprintf("not find info\n"); + } + } + 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; +} + +static int wifi_ap(int argc, char *argv[]) +{ + const char *ssid = RT_NULL; + const char *key = RT_NULL; + + if (argc == 3) + { + ssid = argv[2]; + } + else if (argc == 4) + { + ssid = argv[2]; + key = argv[3]; + } + else { - /* no setting file */ return -1; } - if (fd >= 0) - { - 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); - } - - if (json) - { - cJSON *wifi = cJSON_GetObjectItem(json, "wifi"); - cJSON *ssid = cJSON_GetObjectItem(wifi, "SSID"); - cJSON *key = cJSON_GetObjectItem(wifi, "Key"); - cJSON *mode = cJSON_GetObjectItem(wifi, "Mode"); - - if (ssid) - { - memset(wifi_ssid, 0x0, sizeof(wifi_ssid)); - rt_strncpy(wifi_ssid, ssid->valuestring, sizeof(wifi_ssid) - 1); - } - - if (key) - { - memset(wifi_key, 0x0, sizeof(wifi_key)); - rt_strncpy(wifi_key, key->valuestring, sizeof(wifi_key) - 1); - } - - if (mode) - { - network_mode = mode->valueint; - } - - cJSON_Delete(json); - } - + rt_wlan_start_ap(ssid, key); return 0; } -int wifi_save_cfg(const char *filename) +static int list_sta(int argc, char *argv[]) { - int fd; - cJSON *json = RT_NULL; + struct rt_wlan_info *sta_info; + int num, i; - fd = open(filename, O_RDONLY, 0); - if (fd >= 0) + 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) { - 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); - } - 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); - + rt_kprintf("num:%d\n", num); return 0; } - - if (json) + rt_wlan_ap_get_sta_info(sta_info, num); + rt_kprintf("num:%d\n", num); + for (i = 0; i < num; i++) { - cJSON *wifi = cJSON_GetObjectItem(json, "wifi"); - if (!wifi) - { - wifi = cJSON_CreateObject(); - cJSON_AddItemToObject(json, "wifi", wifi); - } + 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; +} - 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); - - 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); +static int wifi_disconnect(int argc, char *argv[]) +{ + if (argc != 2) + { + return -1; } + rt_wlan_disconnect(); return 0; } -#endif -int wifi_save_setting(void) +static int wifi_ap_stop(int argc, char *argv[]) { -#ifdef PKG_USING_CJSON - wifi_save_cfg(WIFI_SETTING_FN); -#endif - - return 0; -} -#endif - -int wifi_softap_setup_netif(struct netif *netif) -{ - 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) - { - rt_kprintf("no wlan:%s device\n", WIFI_DEVICE_AP_NAME); - return -1; - } - - 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) - { - result = rt_wlan_softap(wlan, &info, wifi_key); - } + return -1; } - return result; + if (ssid != RT_NULL) + { + len = rt_strlen(ssid); + if (len > RT_WLAN_SSID_MAX_LENGTH) + { + rt_kprintf("ssid is to long"); + return 0; + } + rt_memcpy(&cfg_info.info.ssid.val[0], ssid, len); + cfg_info.info.ssid.len = len; + } + + if (password != RT_NULL) + { + len = rt_strlen(password); + if (len > RT_WLAN_PASSWORD_MAX_LENGTH) + { + rt_kprintf("password is to long"); + return 0; + } + rt_memcpy(&cfg_info.key.val[0], password, len); + cfg_info.key.len = len; + } + + 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"); -} - -int wifi(int argc, char **argv) -{ - struct rt_wlan_device *wlan; - if (argc == 1) { - wifi_default(); - return 0; + rt_wlan_cfg_dump(); } - - 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_clear_cfg(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); - - network_mode = WIFI_STATION; - -#ifdef PKG_USING_CJSON - wifi_save_cfg(WIFI_SETTING_FN); -#endif - - return 0; + rt_wlan_cfg_delete_all(); + rt_wlan_cfg_cache_save(); } - - /* get wlan device */ - wlan = (struct rt_wlan_device *)rt_device_find(argv[1]); - if (!wlan) + else { - rt_kprintf("no wlan:%s device\n", argv[1]); - return 0; + return -1; } + return 0; +} + +static int wifi_debug_dump_prot(int argc, char *argv[]) +{ + if (argc == 1) + { + rt_wlan_prot_dump(); + } + else + { + return -1; + } + return 0; +} + +static int wifi_debug_set_mode(int argc, char *argv[]) +{ + rt_wlan_mode_t mode; + + if (argc != 3) + return -1; + + if (rt_strcmp("sta", argv[1]) == 0) + { + mode = RT_WLAN_STATION; + } + else if (rt_strcmp("ap", argv[1]) == 0) + { + mode = RT_WLAN_AP; + } + else + return -1; + + rt_wlan_set_mode(argv[2], mode); + return 0; +} + +static int wifi_debug_set_prot(int argc, char *argv[]) +{ + if (argc != 3) + { + return -1; + } + + rt_wlan_prot_attach(argv[2], argv[1]); + return 0; +} + +static int wifi_debug_set_autoconnect(int argc, char *argv[]) +{ + if (argc == 2) + { + 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 + { + return -1; + } + 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) { - wifi_usage(); + wifi_debug_help(0, RT_NULL); return 0; } - if (strcmp(argv[2], "join") == 0) + for (i = 0; i < sizeof(debug_tab) / sizeof(debug_tab[0]); i++) { - rt_wlan_init(wlan, WIFI_STATION); - network_mode = WIFI_STATION; - - /* 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) - { - /* the key was saved in wlan device */ - rt_wlan_connect(wlan, RT_NULL, wlan->key); - } - else if (strcmp(argv[2], "down") == 0) - { - rt_wlan_disconnect(wlan); - rt_wlan_info_deinit(&info); - } - else if (strcmp(argv[2], "scan") == 0) - { - struct rt_wlan_scan_result *scan_result = RT_NULL; - - rt_wlan_scan(wlan, &scan_result); - if (scan_result) + 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); - } - } - rt_wlan_release_scan_result(&scan_result); - } - else if (strcmp(argv[2], "rssi") == 0) - { - int rssi; - - rssi = rt_wlan_get_rssi(wlan); - rt_kprintf("rssi=%d\n", rssi); - } - else if (strcmp(argv[2], "ap") == 0) - { - rt_err_t result = RT_EOK; - - 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(); - } - - if (result != RT_EOK) - { - rt_kprintf("wifi start failed! result=%d\n", result); + run_cmd = &debug_tab[i]; + break; } } - else if (strcmp(argv[2], "status") == 0) + + if (run_cmd == RT_NULL) { - int rssi; - - 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 - { - rt_kprintf("wifi disconnected!\n"); - } - + wifi_debug_help(0, RT_NULL); return 0; } + if (run_cmd->fun != RT_NULL) + { + result = run_cmd->fun(argc - 2, &argv[2]); + } + + if (result) + { + wifi_debug_help(argc - 2, &argv[2]); + } return 0; } -MSH_CMD_EXPORT(wifi, wifi command); + +static int wifi_msh(int argc, char *argv[]) +{ + int i, result = 0; + const struct wifi_cmd_des *run_cmd = RT_NULL; + + if (argc == 1) + { + wifi_help(argc, argv); + return 0; + } + + /* find fun */ + for (i = 0; i < sizeof(cmd_tab) / sizeof(cmd_tab[0]); i++) + { + if (rt_strcmp(cmd_tab[i].cmd, argv[1]) == 0) + { + 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; +} + +FINSH_FUNCTION_EXPORT_ALIAS(wifi_msh, __cmd_wifi, wifi command.); diff --git a/components/drivers/wlan/wlan_cmd.h b/components/drivers/wlan/wlan_cmd.h deleted file mode 100644 index a981601f5e..0000000000 --- a/components/drivers/wlan/wlan_cmd.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * File : wlan_cmd.h - * Wi-Fi common commands - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Change Logs: - * Date Author Notes - * 2018-06-05 RT-Thread first version - */ - -#ifndef WLAN_CMD_H__ -#define WLAN_CMD_H__ - -struct netif; - -int wifi_get_mode(void); -int wifi_set_mode(int mode); - -/* do the wifi default action: read wifi setting and then join or start soft-AP */ -int wifi_default(void); -/* setup netif for soft-ap */ -int wifi_softap_setup_netif(struct netif *netif); - -int wifi_set_setting(const char *ssid, const char *pwd); - -#ifdef PKG_USING_CJSON -int wifi_read_cfg(const char *filename); -int wifi_save_cfg(const char *filename); -#endif -/* save wifi setting with default storage file */ -int wifi_save_setting(void); - -extern struct rt_wlan_info info; - -#endif diff --git a/components/drivers/wlan/wlan_dev.c b/components/drivers/wlan/wlan_dev.c index a42072692c..6892aed6d3 100644 --- a/components/drivers/wlan/wlan_dev.c +++ b/components/drivers/wlan/wlan_dev.c @@ -1,328 +1,745 @@ /* - * 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 #include -#include +#include +#include -#include "wlan_dev.h" -#include "wlan_cmd.h" +#define DBG_ENABLE +#define DBG_LEVEL DBG_INFO +#define DBG_SECTION_NAME "WLAN.dev" +#define DBG_COLOR +#include -#define NIOCTL_SADDR 0x02 +#ifndef RT_DEVICE +#define RT_DEVICE(__device) ((rt_device_t)__device) +#endif -void rt_wlan_info_init(struct rt_wlan_info *info, rt_wlan_mode_t mode, rt_wlan_security_t security, - char *ssid) +#define WLAN_DEV_LOCK(_wlan) (rt_mutex_take(&(_wlan)->lock, RT_WAITING_FOREVER)) +#define WLAN_DEV_UNLOCK(_wlan) (rt_mutex_release(&(_wlan)->lock)) + +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) + 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; +} + +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 result = RT_EOK; + struct rt_sta_info sta_info; + + if (device == RT_NULL) + { + return -RT_EIO; + } + if (info == RT_NULL) + { + return -RT_ERROR; + } + + if ((password_len > RT_WLAN_PASSWORD_MAX_LENGTH) || + (info->ssid.len > RT_WLAN_SSID_MAX_LENGTH)) + { + LOG_E("L:%d password or ssid is to long", __LINE__); + return -RT_ERROR; + } + rt_memset(&sta_info, 0, sizeof(struct rt_sta_info)); + rt_memcpy(&sta_info.ssid, &info->ssid, sizeof(rt_wlan_ssid_t)); + rt_memcpy(sta_info.bssid, info->bssid, RT_WLAN_BSSID_MAX_LENGTH); + if (password != RT_NULL) + { + rt_memcpy(sta_info.key.val, password, password_len); + sta_info.key.len = password_len; + } + sta_info.channel = info->channel; + sta_info.security = info->security; + + result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_JOIN, &sta_info); + return result; +} + +rt_err_t rt_wlan_dev_disconnect(struct rt_wlan_device *device) +{ + rt_err_t result = RT_EOK; + + 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 == 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(&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; +} + +rt_err_t rt_wlan_dev_ap_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_AP_STOP, RT_NULL); + return result; +} + +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_dev_get_rssi(struct rt_wlan_device *device) +{ + int rssi = 0; + + if (device == RT_NULL) + { + return -RT_EIO; + } + + 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) + { + return -RT_EIO; + } + + 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) + { + return -RT_EIO; + } + + result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_SET_MAC, &mac[0]); + return result; +} + +rt_err_t rt_wlan_dev_enable_powersave(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_POWERSAVE, &enable); + return result; +} + +rt_err_t rt_wlan_dev_disable_powersave(struct rt_wlan_device *device) +{ + 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_POWERSAVE, &enable); + return result; +} + +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) +{ + int i = 0; + rt_base_t level; + + if (device == RT_NULL) + { + return -RT_EIO; + } + if (event >= RT_WLAN_DEV_EVT_MAX) + { + return -RT_EINVAL; + } + + level = rt_hw_interrupt_disable(); + for (i = 0; i < RT_WLAN_DEV_EVENT_NUM; i++) + { + if (device->handler_table[event][i].handler == RT_NULL) { - strncpy((char *)info->ssid, (char *)ssid, strlen((char *)ssid) + 1); + 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); + + /* No space found */ + return -RT_ERROR; +} + +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 i = 0; + rt_base_t level; + + if (device == RT_NULL) + { + return -RT_EIO; + } + if (event >= RT_WLAN_DEV_EVT_MAX) + { + return -RT_EINVAL; + } + + level = rt_hw_interrupt_disable(); + for (i = 0; i < RT_WLAN_DEV_EVENT_NUM; i++) + { + if (device->handler_table[event][i].handler == 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; +} + +void rt_wlan_dev_indicate_event_handle(struct rt_wlan_device *device, rt_wlan_dev_event_t event, struct rt_wlan_buff *buff) +{ + 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; + } + + /* 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); + + /* run callback */ + for (i = 0; i < RT_WLAN_DEV_EVENT_NUM; i++) + { + if (handler[i] != RT_NULL) + { + handler[i](device, event, buff, parameter[i]); } } } -void rt_wlan_info_deinit(struct rt_wlan_info *info) +rt_err_t rt_wlan_dev_enter_pormisc(struct rt_wlan_device *device) { - if (info->ssid) + rt_err_t result = RT_EOK; + int enable = 1; + + if (device == RT_NULL) { - rt_free(info->ssid); - info->ssid = RT_NULL; + return -RT_EIO; } - memset(info, 0x0, sizeof(struct rt_wlan_info)); -} - -int rt_wlan_init(struct rt_wlan_device *device, rt_wlan_mode_t mode) -{ - int result; - - if (device == RT_NULL) return 0; - - if (device->info == RT_NULL) - { - struct rt_wlan_info *info; - char *ssid; - - info = rt_malloc(sizeof(struct rt_wlan_info)); - if (info) - { - ssid = rt_malloc(SSID_LENGTH_MAX_SIZE); - info->ssid = ssid; - } - device->info = info; - } - - result = rt_device_control(RT_DEVICE(device), WIFI_INIT, (void *)&mode); - + result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_CFG_PROMISC, &enable); return result; } -int rt_wlan_connect(struct rt_wlan_device *device, struct rt_wlan_info *info, char *password) +rt_err_t rt_wlan_dev_exit_pormisc(struct rt_wlan_device *device) { - int result = 0; + rt_err_t result = RT_EOK; + int enable = 0; - if (device == RT_NULL) return -RT_EIO; - - 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), WIFI_EASYJOIN, (void *)password); - + result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_CFG_PROMISC, &enable); return result; } -int rt_wlan_softap(struct rt_wlan_device *device, struct rt_wlan_info *info, char *password) +rt_err_t rt_wlan_dev_set_pormisc_callback(struct rt_wlan_device *device, rt_wlan_pormisc_callback_t callback) { - int result = RT_EOK; - - if (device == RT_NULL) return -RT_EIO; - - if (info != RT_NULL) + if (device == RT_NULL) { - rt_wlan_set_info(device, info); + return -RT_EIO; } - - if (password == NULL) - { - memset(device->key, 0, sizeof(device->key)); - } - else - { - 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); - } - - result = rt_device_control(RT_DEVICE(device), WIFI_SOFTAP, (void *)password); - - return result; -} - -int rt_wlan_disconnect(struct rt_wlan_device *device) -{ - int result = 0; - - if (device == RT_NULL) return -RT_EIO; - - /* save event handler */ - result = rt_device_control(RT_DEVICE(device), WIFI_DISCONNECT, RT_NULL); - - return result; -} - -int rt_wlan_set_info(struct rt_wlan_device *device, struct rt_wlan_info *info) -{ - 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; + device->pormisc_callback = callback; return RT_EOK; } -struct rt_wlan_info *rt_wlan_get_info(struct rt_wlan_device *device) +void rt_wlan_dev_pormisc_handler(struct rt_wlan_device *device, void *data, int len) { - struct rt_wlan_info *info = RT_NULL; + rt_wlan_pormisc_callback_t callback; - if (device != RT_NULL) + if (device == RT_NULL) { - info = device->info; + return; } - return info; + callback = device->pormisc_callback; + + if (callback != RT_NULL) + { + callback(device, data, len); + } } -int rt_wlan_scan(struct rt_wlan_device *device, struct rt_wlan_scan_result **scan_result) +rt_err_t rt_wlan_dev_cfg_filter(struct rt_wlan_device *device, struct rt_wlan_filter *filter) { - int result; + rt_err_t result = RT_EOK; - result = rt_device_control(RT_DEVICE(device), WIFI_SCAN, scan_result); + 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_get_rssi(struct rt_wlan_device *device) +rt_err_t rt_wlan_dev_set_channel(struct rt_wlan_device *device, int channel) { - int rssi; - int result; + rt_err_t result = RT_EOK; - if (device == RT_NULL) return 0; - result = rt_device_control(RT_DEVICE(device), WIFI_GET_RSSI, (void *)&rssi); - - if (result == RT_EOK) return rssi; + if (device == RT_NULL) + { + return -RT_EIO; + } + if (channel < 0) + { + return -RT_ERROR; + } + result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_SET_CHANNEL, &channel); return result; } -int rt_wlan_get_mac(struct rt_wlan_device *device, rt_uint8_t hwaddr[6]) +rt_err_t rt_wlan_dev_get_channel(struct rt_wlan_device *device) { - int result; - if (device == RT_NULL) return 0; - result = rt_device_control(RT_DEVICE(device), NIOCTL_GADDR, (void *)hwaddr); - return result; -} + rt_err_t result = RT_EOK; + int channel; -int rt_wlan_set_mac(struct rt_wlan_device *device, rt_uint8_t hwaddr[6]) -{ - 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; + } -int rt_wlan_enter_powersave(struct rt_wlan_device *device, int level) -{ - int result = 0; - - if (device == RT_NULL) return -RT_EIO; - - result = rt_device_control(RT_DEVICE(device), WIFI_ENTER_POWERSAVE, (void *)&level); - - return result; -} - -int rt_wlan_register_event_handler(struct rt_wlan_device *device, rt_wlan_event_t event, - rt_wlan_event_handler handler) -{ - if (device == RT_NULL) return -RT_EIO; - if (event >= WIFI_EVT_MAX) return -RT_EINVAL; - - device->handler[event] = handler; - - return RT_EOK; -} - -int rt_wlan_unregister_event_handler(struct rt_wlan_device *device, rt_wlan_event_t event) -{ - if (device == RT_NULL) return -RT_EIO; - if (event >= WIFI_EVT_MAX) return -RT_EINVAL; - - device->handler[event] = RT_NULL; - - return RT_EOK; -} - -int rt_wlan_indicate_event_handle(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data) -{ - if (device == RT_NULL) return -RT_EIO; - if (event >= WIFI_EVT_MAX) return -RT_EINVAL; - - if (device->handler[event] != RT_NULL) - device->handler[event](device, event, user_data); - - return RT_EOK; -} - -int rt_wlan_cfg_monitor(struct rt_wlan_device *device, rt_wlan_monitor_opition_t opition) -{ - int result = 0; - - if (device == RT_NULL) return -RT_EIO; - - result = rt_device_control(RT_DEVICE(device), WIFI_CFG_MONITOR, (void *)&opition); - - return result; -} - -int rt_wlan_set_monitor_callback(struct rt_wlan_device *device, rt_wlan_monitor_callback_t callback) -{ - int result = 0; - - if (device == RT_NULL) return -RT_EIO; - - result = rt_device_control(RT_DEVICE(device), WIFI_SET_MONITOR_CALLBACK, (void *)callback); - - return result; -} - -int rt_wlan_set_channel(struct rt_wlan_device *device, int channel) -{ - int result = 0; - - if (device == RT_NULL) return -RT_EIO; - - result = rt_device_control(RT_DEVICE(device), WIFI_SET_CHANNEL, (void *)&channel); - - return result; -} - -int rt_wlan_get_channel(struct rt_wlan_device *device) -{ - int channel = 0; - - if (device == RT_NULL) return -RT_EIO; - - rt_device_control(RT_DEVICE(device), WIFI_GET_CHANNEL, &channel); + result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_GET_CHANNEL, &channel); + if (result != RT_EOK) + { + return -1; + } return channel; } -void rt_wlan_release_scan_result(struct rt_wlan_scan_result **scan_result) +rt_err_t rt_wlan_dev_set_country(struct rt_wlan_device *device, rt_country_code_t country_code) { - int i, ap_num; - struct rt_wlan_scan_result *_scan_result; + int result = RT_EOK; - if (*scan_result != RT_NULL) + if (device == 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; + return -RT_EIO; } - rt_free(*scan_result); - *scan_result = RT_NULL; - scan_result = RT_NULL; + + result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_SET_COUNTRY, &country_code); + return result; +} + +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 country_code; + } + + result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_GET_COUNTRY, &country_code); + if (result != RT_EOK) + { + return RT_COUNTRY_UNKNOWN; + } + + return country_code; +} + +rt_err_t rt_wlan_dev_scan(struct rt_wlan_device *device, struct rt_wlan_info *info) +{ + 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 (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; +} + +rt_err_t rt_wlan_dev_report_data(struct rt_wlan_device *device, void *buff, int len) +{ + 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; + + rt_mutex_init(&wlan->lock, "wlan_dev", RT_IPC_FLAG_FIFO); + + 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; +} + +static rt_err_t _rt_wlan_dev_control(rt_device_t dev, int cmd, void *args) +{ + struct rt_wlan_device *wlan = (struct rt_wlan_device *)dev; + rt_err_t err = RT_EOK; + + RT_ASSERT(dev != RT_NULL); + + WLAN_DEV_LOCK(wlan); + + 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; +} + +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) +{ + struct rt_wlan_device *wlan; + + if (name == RT_NULL || ops == 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_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; } diff --git a/components/drivers/wlan/wlan_dev.h b/components/drivers/wlan/wlan_dev.h index df7244fd6f..c382df8867 100644 --- a/components/drivers/wlan/wlan_dev.h +++ b/components/drivers/wlan/wlan_dev.h @@ -1,72 +1,65 @@ /* - * 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 -#include +#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; + 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; -/* wifi network information */ -struct rt_wlan_info +typedef enum { - rt_wlan_mode_t mode; /* wifi mode */ - rt_wlan_security_t security; - - char *ssid; - uint8_t bssid[6]; - - /* maximal data rate */ - uint32_t datarate; - /* radio channel */ - uint16_t channel; - /* signal strength */ - int16_t rssi; -}; - -struct rt_wlan_info_request -{ - uint16_t req_number; /* the number of information item for request */ - uint16_t rsp_number; /* the number of information item for response */ - - struct rt_wlan_info *infos;/* the array of information to save response */ -}; - -typedef struct rt_wlan_scan_result -{ - char ap_num; - struct rt_wlan_info *ap_table; -} rt_wlan_scan_result_t; + 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; -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_buff; + +typedef void (*rt_wlan_dev_event_handler)(struct rt_wlan_device *device, rt_wlan_dev_event_t event, struct rt_wlan_buff *buff, void *parameter); + +typedef void (*rt_wlan_pormisc_callback_t)(struct rt_wlan_device *device, void *data, int len); + +struct rt_wlan_ssid { - struct eth_device parent; + 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_info *info; - char key[KEY_ARRAY_SIZE + 1]; +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; - rt_wlan_event_handler handler[WIFI_EVT_MAX]; - void *user_data; - int interface; +#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 */ + rt_uint32_t datarate; + /* radio channel */ + rt_int16_t channel; + /* signal strength */ + rt_int16_t rssi; + /* ssid */ + rt_wlan_ssid_t ssid; + /* hwaddr */ + rt_uint8_t bssid[RT_WLAN_BSSID_MAX_LENGTH]; + rt_uint8_t hidden; }; -/* - * 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_wlan_buff +{ + void *data; + rt_int32_t len; +}; -/* - * Wi-Fi Manager APIs - */ -int rt_wlan_init(struct rt_wlan_device *device, rt_wlan_mode_t mode); +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) */ +}; -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); +typedef enum +{ + 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; -int rt_wlan_softap(struct rt_wlan_device *device, struct rt_wlan_info *info, - char *password); +struct rt_wlan_filter +{ + struct rt_filter_pattern patt; + rt_filter_rule_t rule; + rt_uint8_t enable; +}; -/* 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); +struct rt_wlan_dev_event_desc +{ + rt_wlan_dev_event_handler handler; + void *parameter; +}; -/* 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); +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; +}; -/* 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]); +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; +}; -/* enter power save level */ -int rt_wlan_enter_powersave(struct rt_wlan_device *device, int level); +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; +}; -/* 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); +struct rt_scan_info +{ + rt_wlan_ssid_t ssid; + rt_uint8_t bssid[6]; + rt_int16_t channel_min; + rt_int16_t channel_max; +}; -/* un-register the event handler */ -int rt_wlan_unregister_event_handler(struct rt_wlan_device *device, rt_wlan_event_t event); +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); +}; -/* 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_init(struct rt_wlan_device *device, rt_wlan_mode_t mode); -/* 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_connect(struct rt_wlan_device *device, struct rt_wlan_info *info, const char *password, int password_len); -/* set callback function for monitor mode*/ -int rt_wlan_set_monitor_callback(struct rt_wlan_device *device, rt_wlan_monitor_callback_t callback); +rt_err_t rt_wlan_dev_disconnect(struct rt_wlan_device *device); -/* Set the monitor channel */ -int rt_wlan_set_channel(struct rt_wlan_device *device, int channel); +rt_err_t rt_wlan_dev_ap_start(struct rt_wlan_device *device, struct rt_wlan_info *info, const char *password, int password_len); -void rt_wlan_release_scan_result(struct rt_wlan_scan_result **scan_result); +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]); + +rt_err_t rt_wlan_dev_enable_powersave(struct rt_wlan_device *device); + +rt_err_t rt_wlan_dev_disable_powersave(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); + +rt_err_t rt_wlan_dev_unregister_event_handler(struct rt_wlan_device *device, rt_wlan_dev_event_t event, rt_wlan_dev_event_handler handler); + +void rt_wlan_dev_indicate_event_handle(struct rt_wlan_device *device, rt_wlan_dev_event_t event, struct rt_wlan_buff *buff); + +rt_err_t rt_wlan_dev_enter_pormisc(struct rt_wlan_device *device); + +rt_err_t rt_wlan_dev_exit_pormisc(struct rt_wlan_device *device); + +rt_err_t rt_wlan_dev_set_pormisc_callback(struct rt_wlan_device *device, rt_wlan_pormisc_callback_t callback); + +void rt_wlan_dev_pormisc_handler(struct rt_wlan_device *device, void *data, int len); + +rt_err_t rt_wlan_dev_cfg_filter(struct rt_wlan_device *device, struct rt_wlan_filter *filter); + +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 diff --git a/components/drivers/wlan/wlan_lwip.c b/components/drivers/wlan/wlan_lwip.c new file mode 100644 index 0000000000..c9f1f875a0 --- /dev/null +++ b/components/drivers/wlan/wlan_lwip.c @@ -0,0 +1,478 @@ +/* + * 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 +#include +#include +#include +#include +#ifdef RT_USING_LWIP +#include +#include +#ifdef LWIP_USING_DHCPD +#include +#endif + +#define DBG_ENABLE +#define DBG_LEVEL DBG_INFO +#define DBG_SECTION_NAME "WLAN.lwip" +#define DBG_COLOR +#include + +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(ð_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(ð_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 diff --git a/components/drivers/wlan/wlan_mgnt.c b/components/drivers/wlan/wlan_mgnt.c index 2a728747f2..4474f25050 100644 --- a/components/drivers/wlan/wlan_mgnt.c +++ b/components/drivers/wlan/wlan_mgnt.c @@ -1,142 +1,1901 @@ /* - * 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 #include -#include +#include +#include +#include +#include +#include -#include +#define DBG_ENABLE +#define DBG_LEVEL DBG_INFO +#define DBG_SECTION_NAME "WLAN.mgnt" +#define DBG_COLOR +#include -#include "wlan_dev.h" -#include "wlan_cmd.h" - -#define WLAN_MGNT_DEBUG 1 - -#if WLAN_MGNT_DEBUG -#define WLAN_MGNT_DBG(...) rt_kprintf("[WLAN_MGNT]"),rt_kprintf(__VA_ARGS__) -#else -#define WLAN_MGNT_DBG(...) +#ifndef RT_WLAN_DEVICE +#define RT_WLAN_DEVICE(__device) ((struct rt_wlan_device *)__device) #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 +#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__) -static void wlan_mgnt_init_done_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data) +#define STA_DEVICE() (_sta_mgnt.device) +#define AP_DEVICE() (_ap_mgnt.device) + +#define SRESULT_LOCK() (rt_mutex_take(&scan_result_mutex, RT_WAITING_FOREVER)) +#define SRESULT_UNLOCK() (rt_mutex_release(&scan_result_mutex)) + +#define STAINFO_LOCK() (rt_mutex_take(&sta_info_mutex, RT_WAITING_FOREVER)) +#define STAINFO_UNLOCK() (rt_mutex_release(&sta_info_mutex)) + +#define MGNT_LOCK() (rt_mutex_take(&mgnt_mutex, RT_WAITING_FOREVER)) +#define MGNT_UNLOCK() (rt_mutex_release(&mgnt_mutex)) + +#define COMPLETE_LOCK() (rt_mutex_take(&complete_mutex, RT_WAITING_FOREVER)) +#define COMPLETE_UNLOCK() (rt_mutex_release(&complete_mutex)) + +#define TIME_STOP() (rt_timer_stop(&reconnect_time)) +#define TIME_START() (rt_timer_start(&reconnect_time)) + +#define DISCONNECT_RESPONSE_TICK (2000) + +struct rt_wlan_mgnt_des { - WLAN_MGNT_DBG("wlan init done event callback \n"); + 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_link_up_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data) +rt_inline int _ap_is_null(void) { - WLAN_MGNT_DBG("wlan link up event callback \n"); + if (_ap_mgnt.device == RT_NULL) + { + return 1; + } + return 0; } -static void wlan_mgnt_link_down_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data) +rt_inline rt_bool_t _is_do_connect(void) { - WLAN_MGNT_DBG("wlan link down event callback \n"); + if ((rt_wlan_get_autoreconnect_mode() == RT_FALSE) || + (rt_wlan_is_connected() == RT_TRUE) || + (_sta_mgnt.state & RT_WLAN_STATE_CONNECTING)) + { + return RT_FALSE; + } + return RT_TRUE; } -static void wlan_mgnt_sta_connect_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data) +static void rt_wlan_mgnt_work(void *parameter); + +static rt_err_t rt_wlan_send_msg(rt_wlan_dev_event_t event, void *buff, int len) { - WLAN_MGNT_DBG("wlan sta connect event callback \n"); - struct netif *netif = device->parent.netif; + struct rt_wlan_msg *msg; - netifapi_netif_set_up(netif); - netifapi_netif_set_link_up(netif); -#ifdef RT_LWIP_DHCP - /* start DHCP */ - dhcp_start(netif); -#endif -} + RT_WLAN_LOG_D("F:%s is run event:%d", __FUNCTION__, event); -static void wlan_mgnt_sta_disconnect_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data) -{ - 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); -#endif -} - -static void wlan_mgnt_ap_start_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data) -{ - WLAN_MGNT_DBG("wlan ap start event callback \n"); - netifapi_netif_set_up(device->parent.netif); - netifapi_netif_set_link_up(device->parent.netif); - - wifi_softap_setup_netif(device->parent.netif); -} - - -static void wlan_mgnt_ap_stop_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data) -{ - WLAN_MGNT_DBG("wlan ap stop event callback \n"); - - netifapi_netif_set_down(device->parent.netif); - netifapi_netif_set_link_down(device->parent.netif); -} - -static void wlan_mgnt_ap_associate_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data) -{ - WLAN_MGNT_DBG("wlan ap associate event callback \n"); -} - -static void wlan_mgnt_ap_disassociate_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data) -{ - WLAN_MGNT_DBG("wlan ap disassociate event callback \n"); -} - -static void wlan_mgnt_scan_done_event(struct rt_wlan_device *device, rt_wlan_event_t event, void *user_data) -{ - WLAN_MGNT_DBG("wlan scan done event callback \n"); -} - -int rt_wlan_mgnt_attach(struct rt_wlan_device *device, void *user_data) -{ - RT_ASSERT(device != RT_NULL); - - 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); + /* 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 rt_err_t rt_wlan_scan_result_cache(struct rt_wlan_info *info, int timeout) +{ + struct rt_wlan_info *ptable; + rt_err_t err = RT_EOK; + int i, insert = -1; + + if (_sta_is_null() || (info == RT_NULL)) return RT_EOK; + + RT_WLAN_LOG_D("ssid:%s len:%d mac:%02x:%02x:%02x:%02x:%02x:%02x", info->ssid.val, info->ssid.len, + info->bssid[0], info->bssid[1], info->bssid[2], info->bssid[3], info->bssid[4], info->bssid[5]); + + err = rt_mutex_take(&scan_result_mutex, rt_tick_from_millisecond(timeout)); + if (err != RT_EOK) + return err; + + /* de-duplicatio */ + for (i = 0; i < scan_result.num; i++) + { + if ((info->ssid.len == scan_result.info[i].ssid.len) && + (rt_memcmp(&info->bssid[0], &scan_result.info[i].bssid[0], RT_WLAN_BSSID_MAX_LENGTH) == 0)) + { + rt_mutex_release(&scan_result_mutex); + return RT_EOK; + } +#ifdef RT_WLAN_SCAN_SORT + if (insert >= 0) + { + continue; + } + /* Signal intensity comparison */ + if ((info->rssi < 0) && (scan_result.info[i].rssi < 0)) + { + if (info->rssi > scan_result.info[i].rssi) + { + insert = i; + continue; + } + else if (info->rssi < scan_result.info[i].rssi) + { + continue; + } + } + + /* Channel comparison */ + if (info->channel < scan_result.info[i].channel) + { + insert = i; + continue; + } + else if (info->channel > scan_result.info[i].channel) + { + continue; + } + + /* data rate comparison */ + if ((info->datarate > scan_result.info[i].datarate)) + { + insert = i; + continue; + } + else if (info->datarate < scan_result.info[i].datarate) + { + continue; + } +#endif + } + + /* Insert the end */ + if (insert == -1) + insert = scan_result.num; + + if (scan_result.num >= RT_WLAN_SCAN_CACHE_NUM) + return RT_EOK; + + /* malloc memory */ + ptable = rt_malloc(sizeof(struct rt_wlan_info) * (scan_result.num + 1)); + if (ptable == RT_NULL) + { + rt_mutex_release(&scan_result_mutex); + RT_WLAN_LOG_E("wlan info malloc failed!"); + return -RT_ENOMEM; + } + scan_result.num ++; + + /* copy info */ + for (i = 0; i < scan_result.num; i++) + { + if (i < insert) + { + ptable[i] = scan_result.info[i]; + } + else if (i > insert) + { + ptable[i] = scan_result.info[i - 1]; + } + else if (i == insert) + { + ptable[i] = *info; + } + } + rt_free(scan_result.info); + scan_result.info = ptable; + rt_mutex_release(&scan_result_mutex); + return err; +} + +static rt_err_t rt_wlan_sta_info_add(struct rt_wlan_info *info, int timeout) +{ + struct rt_wlan_sta_list *sta_list; + rt_err_t err = RT_EOK; + + if (_ap_is_null() || (info == RT_NULL)) return RT_EOK; + + err = rt_mutex_take(&sta_info_mutex, rt_tick_from_millisecond(timeout)); + if (err == RT_EOK) + { + /* malloc memory */ + sta_list = rt_malloc(sizeof(struct rt_wlan_sta_list)); + if (sta_list == RT_NULL) + { + rt_mutex_release(&sta_info_mutex); + RT_WLAN_LOG_E("sta list malloc failed!"); + return -RT_ENOMEM; + } + sta_list->next = RT_NULL; + sta_list->info = *info; + + /* Append sta info */ + sta_list->next = sta_info.node; + sta_info.node = sta_list; + /* num++ */ + sta_info.num ++; + rt_mutex_release(&sta_info_mutex); + RT_WLAN_LOG_I("sta associated mac:%02x:%02x:%02x:%02x:%02x:%02x", + info->bssid[0], info->bssid[1], info->bssid[2], + info->bssid[3], info->bssid[4], info->bssid[5]); + } + return err; +} + +static rt_err_t rt_wlan_sta_info_del(struct rt_wlan_info *info, int timeout) +{ + struct rt_wlan_sta_list *sta_list, *sta_prve; + rt_err_t err = RT_EOK; + + if (_ap_is_null() || (info == RT_NULL)) return RT_EOK; + + err = rt_mutex_take(&sta_info_mutex, rt_tick_from_millisecond(timeout)); + if (err == RT_EOK) + { + /* traversing the list */ + for (sta_list = sta_info.node, sta_prve = RT_NULL; sta_list != RT_NULL; + sta_prve = sta_list, sta_list = sta_list->next) + { + /* find mac addr */ + if (rt_memcmp(&sta_list->info.bssid[0], &info->bssid[0], RT_WLAN_BSSID_MAX_LENGTH) == 0) + { + if (sta_prve == RT_NULL) + { + sta_info.node = sta_list->next; + } + else + { + sta_prve->next = sta_list->next; + } + sta_info.num --; + rt_free(sta_list); + break; + } + } + rt_mutex_release(&sta_info_mutex); + RT_WLAN_LOG_I("sta exit mac:%02x:%02x:%02x:%02x:%02x:%02x", + info->bssid[0], info->bssid[1], info->bssid[2], + info->bssid[3], info->bssid[4], info->bssid[5]); + } + return err; +} + +static rt_err_t rt_wlan_sta_info_del_all(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 rt_wlan_auto_connect_run(struct rt_work *work, void *parameter) +{ + static rt_uint32_t id = 0; + struct rt_wlan_cfg_info cfg_info; + char *password = RT_NULL; + rt_base_t level; + + RT_WLAN_LOG_D("F:%s is run", __FUNCTION__); + + if (rt_mutex_take(&mgnt_mutex, 0) != RT_EOK) + goto exit; + + /* auto connect status is disable or wifi is connect or connecting, exit */ + if (_is_do_connect() == RT_FALSE) + { + id = 0; + RT_WLAN_LOG_D("not connection"); + goto exit; + } + + /* Read the next configuration */ + rt_memset(&cfg_info, 0, sizeof(struct rt_wlan_cfg_info)); + if (rt_wlan_cfg_read_index(&cfg_info, id ++) == 0) + { + RT_WLAN_LOG_D("read cfg fail"); + id = 0; + goto exit; + } + + if (id >= rt_wlan_cfg_get_num()) id = 0; + + if ((cfg_info.key.len > 0) && (cfg_info.key.len < RT_WLAN_PASSWORD_MAX_LENGTH)) + { + cfg_info.key.val[cfg_info.key.len] = '\0'; + password = (char *)(&cfg_info.key.val[0]); + } + rt_wlan_connect_adv(&cfg_info.info, password); +exit: + 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; +} + +rt_err_t rt_wlan_disconnect(void) +{ + rt_err_t err; + struct rt_wlan_complete_des *complete; + rt_uint32_t recved = 0, set = 0; + + /* ap dev Can't be empty */ + if (_sta_is_null()) + { + return -RT_EIO; + } + RT_WLAN_LOG_D("%s is run", __FUNCTION__); + + /* run disconnect */ + MGNT_LOCK(); + /* create event wait complete */ + complete = rt_wlan_complete_create("disc"); + if (complete == RT_NULL) + { + MGNT_UNLOCK(); + return -RT_ENOMEM; + } + err = rt_wlan_dev_disconnect(_sta_mgnt.device); + if (err != RT_EOK) + { + RT_WLAN_LOG_E("wifi disconnect fail"); + rt_wlan_complete_delete(complete); + MGNT_UNLOCK(); + return err; + } + /* Initializing events that need to wait */ + set |= 0x1 << RT_WLAN_DEV_EVT_DISCONNECT; + /* Check whether there is a waiting event */ + rt_wlan_complete_wait(complete, set, RT_WLAN_CONNECT_WAIT_MS, &recved); + rt_wlan_complete_delete(complete); + /* check event */ + set = 0x1 << RT_WLAN_DEV_EVT_DISCONNECT; + if (!(recved & set)) + { + RT_WLAN_LOG_E("disconnect failed!"); + MGNT_UNLOCK(); + return -RT_ERROR; + } + RT_WLAN_LOG_I("disconnect success!"); + MGNT_UNLOCK(); + return err; +} + +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__); + + rt_enter_critical(); + *info = _sta_mgnt.info; + rt_exit_critical(); + return RT_EOK; +} + +int rt_wlan_get_rssi(void) +{ + int rssi = 0; + + if (_sta_is_null()) + { + return -RT_EIO; + } + + MGNT_LOCK(); + rssi = rt_wlan_dev_get_rssi(STA_DEVICE()); + RT_WLAN_LOG_D("%s is run rssi:%d", __FUNCTION__, rssi); + MGNT_UNLOCK(); + return rssi; +} + +rt_err_t rt_wlan_start_ap(const char *ssid, const char *password) +{ + rt_err_t err = RT_EOK; + int ssid_len = 0; + struct rt_wlan_info info; + struct rt_wlan_complete_des *complete; + rt_uint32_t set = 0, recved = 0; + + if (_ap_is_null()) + { + return -RT_EIO; + } + if (ssid == RT_NULL) return -RT_EINVAL; + + rt_memset(&info, 0, sizeof(struct rt_wlan_info)); + RT_WLAN_LOG_D("%s is run ssid:%s password:%s", __FUNCTION__, ssid, password); + if (password) + { + info.security = SECURITY_WPA2_AES_PSK; + } + ssid_len = rt_strlen(ssid); + if (ssid_len > RT_WLAN_SSID_MAX_LENGTH) + { + RT_WLAN_LOG_E("ssid is to long! len:%d", ssid_len); + } + + /* copy info */ + rt_memcpy(&info.ssid.val, ssid, ssid_len); + info.ssid.len = ssid_len; + info.channel = 6; + + /* Initializing events that need to wait */ + MGNT_LOCK(); + /* create event wait complete */ + complete = rt_wlan_complete_create("start_ap"); + if (complete == RT_NULL) + { + MGNT_UNLOCK(); + return -RT_ENOMEM; + } + + /* start ap */ + err = rt_wlan_start_ap_adv(&info, password); + if (err != RT_EOK) + { + rt_wlan_complete_delete(complete); + RT_WLAN_LOG_I("start ap failed!"); + MGNT_UNLOCK(); + return err; + } + + /* Initializing events that need to wait */ + set |= 0x1 << RT_WLAN_DEV_EVT_AP_START; + set |= 0x1 << RT_WLAN_DEV_EVT_AP_STOP; + /* Check whether there is a waiting event */ + rt_wlan_complete_wait(complete, set, RT_WLAN_START_AP_WAIT_MS, &recved); + rt_wlan_complete_delete(complete); + /* check event */ + set = 0x1 << RT_WLAN_DEV_EVT_AP_START; + if (!(recved & set)) + { + RT_WLAN_LOG_I("start ap failed!"); + MGNT_UNLOCK(); + return -RT_ERROR; + } + RT_WLAN_LOG_I("start ap successs!"); + MGNT_UNLOCK(); + return err; +} + +rt_err_t rt_wlan_start_ap_adv(struct rt_wlan_info *info, const char *password) +{ + rt_err_t err = RT_EOK; + int password_len = 0; + + if (_ap_is_null()) + { + return -RT_EIO; + } + RT_WLAN_LOG_D("%s is run", __FUNCTION__); + password_len = rt_strlen(password); + if (password_len > RT_WLAN_PASSWORD_MAX_LENGTH) + { + RT_WLAN_LOG_E("key is to long! len:%d", password_len); + return -RT_EINVAL; + } + /* is start up ? */ + MGNT_LOCK(); + if (rt_wlan_ap_is_active()) + { + if ((_ap_mgnt.info.ssid.len == info->ssid.len) && + (_ap_mgnt.info.security == info->security) && + (_ap_mgnt.info.channel == info->channel) && + (_ap_mgnt.info.hidden == info->hidden) && + (_ap_mgnt.key.len == password_len) && + (rt_memcmp(&_ap_mgnt.info.ssid.val[0], &info->ssid.val[0], info->ssid.len) == 0) && + (rt_memcmp(&_ap_mgnt.key.val[0], password, password_len))) + { + RT_WLAN_LOG_D("wifi Already Start"); + MGNT_UNLOCK(); + return RT_EOK; + } + } + + err = rt_wlan_dev_ap_start(AP_DEVICE(), info, password, password_len); + if (err != RT_EOK) + { + MGNT_UNLOCK(); + return err; + } + rt_memcpy(&_ap_mgnt.info, info, sizeof(struct rt_wlan_info)); + rt_memcpy(&_ap_mgnt.key.val, password, password_len); + _ap_mgnt.key.len = password_len; + + MGNT_UNLOCK(); + return err; +} + +int rt_wlan_ap_is_active(void) +{ + int _active = 0; + + if (_ap_is_null()) + { + return 0; + } + + _active = _ap_mgnt.state & RT_WLAN_STATE_ACTIVE ? 1 : 0; + RT_WLAN_LOG_D("%s is run active:%s", __FUNCTION__, _active ? "Active" : "Inactive"); + return _active; +} + +rt_err_t rt_wlan_ap_stop(void) +{ + rt_err_t err = RT_EOK; + struct rt_wlan_complete_des *complete; + rt_uint32_t set = 0, recved = 0; + + if (_ap_is_null()) + { + return -RT_EIO; + } + RT_WLAN_LOG_D("%s is run", __FUNCTION__); + + /* 调用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_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); diff --git a/components/drivers/wlan/wlan_mgnt.h b/components/drivers/wlan/wlan_mgnt.h index b00414c6e2..62e1dbde4a 100644 --- a/components/drivers/wlan/wlan_mgnt.h +++ b/components/drivers/wlan/wlan_mgnt.h @@ -1,34 +1,154 @@ /* - * 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 + +#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 diff --git a/components/drivers/wlan/wlan_prot.c b/components/drivers/wlan/wlan_prot.c new file mode 100644 index 0000000000..011df270ad --- /dev/null +++ b/components/drivers/wlan/wlan_prot.c @@ -0,0 +1,356 @@ +/* + * 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 +#include +#include +#include + +#define DBG_ENABLE +#define DBG_LEVEL DBG_INFO +#define DBG_SECTION_NAME "WLAN.prot" +#define DBG_COLOR +#include + +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); + } + } +} diff --git a/components/drivers/wlan/wlan_prot.h b/components/drivers/wlan/wlan_prot.h new file mode 100644 index 0000000000..13610e754b --- /dev/null +++ b/components/drivers/wlan/wlan_prot.h @@ -0,0 +1,89 @@ +/* + * 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 diff --git a/components/drivers/wlan/wlan_workqueue.c b/components/drivers/wlan/wlan_workqueue.c new file mode 100644 index 0000000000..f65ac95d08 --- /dev/null +++ b/components/drivers/wlan/wlan_workqueue.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-08-19 tyx the first version + */ + +#include +#include +#include +#include + +#define DBG_ENABLE +#define DBG_LEVEL DBG_INFO +#define DBG_SECTION_NAME "WLAN.work" +#define DBG_COLOR +#include + +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); diff --git a/components/drivers/wlan/wlan_workqueue.h b/components/drivers/wlan/wlan_workqueue.h new file mode 100644 index 0000000000..49bc4a5f9f --- /dev/null +++ b/components/drivers/wlan/wlan_workqueue.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-08-19 tyx the first version + */ + +#ifndef __WLAN_WORKQUEUE_H__ +#define __WLAN_WORKQUEUE_H__ + +#include + +#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