Files

481 lines
11 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "system/includes.h"
#include <string.h>
#include "app_log.h"
#include "wifi/wifi_connect.h"
#include "wifi_sta.h"
#include "wifi_manager.h"
static struct wifi_manager_status wifi_manager_status_data;
/*
* 第一次启动 Wi-Fi 前保存的目标凭据。
*
* 当前只保存在 RAM。
*/
static char wifi_manager_target_ssid[33];
static char wifi_manager_target_password[64];
static u8 wifi_manager_target_valid;
/*
* 在 WIFI_EVENT_MODULE_INIT 阶段配置启动 STA。
*
* 当前诊断阶段与已经验证可联网的官方 demo_wifi 保持一致:
*
* force = 0
* 使用 SDK 最后记忆的模式启动。
*
* store = 1
* STA 模式下保存本次默认 SSID / password。
*/
static int wifi_manager_set_startup_sta_mode(void)
{
struct wifi_store_info parm;
int index;
if (!wifi_manager_target_valid) {
return -1;
}
memset(
&parm,
0,
sizeof(parm)
);
parm.mode = STA_MODE;
parm.connect_best_network = 0;
index = parm.mode - STA_MODE;
strncpy(
(char *)parm.ssid[index],
wifi_manager_target_ssid,
sizeof(parm.ssid[index]) - 1
);
strncpy(
(char *)parm.pwd[index],
wifi_manager_target_password,
sizeof(parm.pwd[index]) - 1
);
return wifi_set_default_mode(
&parm,
0, /* force: 与当前官方 demo 测试路径一致 */
1 /* store: STA 默认配置写入 SDK 存储 */
);
}
/*
* AC79NN SDK Wi-Fi 事件回调。
*
* SDK 事件来到这里后直接处理,
* 不经过额外 wifi_event 转发层。
*/
static int wifi_manager_sdk_event_callback(
void *network_ctx,
enum WIFI_EVENT event
)
{
int ret;
int mode_ret;
(void)network_ctx;
switch (event) {
case WIFI_EVENT_MODULE_INIT:
wifi_manager_status_data.module_initialized = 1;
/*
* STA 的通用参数配置。
*/
ret = wifi_sta_configure();
/*
* Wi-Fi 启动时的默认 STA 配置必须在
* WIFI_EVENT_MODULE_INIT 阶段完成。
*/
mode_ret = wifi_manager_set_startup_sta_mode();
APP_LOG(
"[WIFI_MANAGER] module init "
"sta_configure_ret=%d startup_mode_ret=%d\n",
ret,
mode_ret
);
break;
case WIFI_EVENT_MODULE_START:
{
/*
* 与已经验证可联网的官方 demo_wifi 保持一致:
* 开启 CCK / OFDM / HT MCS0~MCS7 全部发送速率。
*
* BIT(0) ~ BIT(19) 全部置位:
* mask = 0x000FFFFF
*/
u32 tx_rate_control_tab =
0
| BIT(0) /* CCK 1M */
| BIT(1) /* CCK 2M */
| BIT(2) /* CCK 5.5M */
| BIT(3) /* OFDM 6M */
| BIT(4) /* MCS0 / 7.2M */
| BIT(5) /* OFDM 9M */
| BIT(6) /* CCK 11M */
| BIT(7) /* OFDM 12M */
| BIT(8) /* MCS1 / 14.4M */
| BIT(9) /* OFDM 18M */
| BIT(10) /* MCS2 / 21.7M */
| BIT(11) /* OFDM 24M */
| BIT(12) /* MCS3 / 28.9M */
| BIT(13) /* OFDM 36M */
| BIT(14) /* MCS4 / 43.3M */
| BIT(15) /* OFDM 48M */
| BIT(16) /* OFDM 54M */
| BIT(17) /* MCS5 / 57.8M */
| BIT(18) /* MCS6 / 65.0M */
| BIT(19); /* MCS7 / 72.2M */
wifi_set_tx_rate_control_tab(
tx_rate_control_tab
);
wifi_manager_status_data.module_started = 1;
APP_LOG(
"[WIFI_MANAGER] module started "
"tx_rate_mask=0x%08x\n",
(unsigned int)tx_rate_control_tab
);
break;
}
case WIFI_EVENT_MODULE_STOP:
wifi_manager_status_data.module_initialized = 0;
wifi_manager_status_data.module_started = 0;
wifi_manager_status_data.sta_started = 0;
wifi_manager_status_data.connecting = 0;
wifi_manager_status_data.sta_associated = 0;
wifi_manager_status_data.network_ready = 0;
APP_LOG("[WIFI_MANAGER] module stopped\n");
break;
case WIFI_EVENT_MODULE_START_ERR:
wifi_manager_status_data.module_started = 0;
wifi_manager_status_data.sta_started = 0;
wifi_manager_status_data.connecting = 0;
wifi_manager_status_data.sta_associated = 0;
wifi_manager_status_data.network_ready = 0;
APP_LOG("[WIFI_MANAGER] module start failed\n");
break;
case WIFI_EVENT_STA_START:
wifi_manager_status_data.sta_started = 1;
APP_LOG("[WIFI_MANAGER] sta started\n");
break;
case WIFI_EVENT_STA_STOP:
wifi_manager_status_data.sta_started = 0;
wifi_manager_status_data.connecting = 0;
wifi_manager_status_data.sta_associated = 0;
wifi_manager_status_data.network_ready = 0;
APP_LOG("[WIFI_MANAGER] sta stopped\n");
break;
/*
* 只表示 802.11 关联成功。
* DHCP 还没有完成,因此不能认为网络已经可用。
*/
case WIFI_EVENT_STA_CONNECT_SUCC:
wifi_manager_status_data.sta_associated = 1;
wifi_manager_status_data.network_ready = 0;
APP_LOG(
"[WIFI_MANAGER] sta associated, waiting dhcp\n"
);
break;
case WIFI_EVENT_STA_DISCONNECT:
wifi_manager_status_data.connecting = 0;
wifi_manager_status_data.sta_associated = 0;
wifi_manager_status_data.network_ready = 0;
APP_LOG("[WIFI_MANAGER] sta disconnected\n");
break;
case WIFI_EVENT_STA_CONNECT_TIMEOUT_NOT_FOUND_SSID:
wifi_manager_status_data.connecting = 0;
wifi_manager_status_data.sta_associated = 0;
wifi_manager_status_data.network_ready = 0;
APP_LOG("[WIFI_MANAGER] ssid not found\n");
break;
case WIFI_EVENT_STA_CONNECT_ASSOCIAT_FAIL:
wifi_manager_status_data.connecting = 0;
wifi_manager_status_data.sta_associated = 0;
wifi_manager_status_data.network_ready = 0;
APP_LOG("[WIFI_MANAGER] association failed\n");
break;
case WIFI_EVENT_STA_CONNECT_ASSOCIAT_TIMEOUT:
wifi_manager_status_data.connecting = 0;
wifi_manager_status_data.sta_associated = 0;
wifi_manager_status_data.network_ready = 0;
APP_LOG("[WIFI_MANAGER] association timeout\n");
break;
/*
* DHCP 成功后,才认为 IPv4 网络真正可用。
*/
case WIFI_EVENT_STA_NETWORK_STACK_DHCP_SUCC:
wifi_manager_status_data.connecting = 0;
wifi_manager_status_data.sta_associated = 1;
wifi_manager_status_data.network_ready = 1;
APP_LOG(
"[WIFI_MANAGER] network ready rssi=%d\n",
(int)wifi_get_rssi()
);
break;
/*
* DHCP 超时不等价于 802.11 已断开。
*/
case WIFI_EVENT_STA_NETWORK_STACK_DHCP_TIMEOUT:
wifi_manager_status_data.connecting = 0;
wifi_manager_status_data.network_ready = 0;
APP_LOG("[WIFI_MANAGER] dhcp timeout\n");
break;
default:
break;
}
return 0;
}
int wifi_manager_init(void)
{
if (wifi_manager_status_data.initialized) {
return 0;
}
/*
* manager 必须在 Wi-Fi 启动前取得 SDK callback 所有权,
* 否则 MODULE_INIT / MODULE_START 等早期事件会丢失。
*/
if (wifi_is_on()) {
APP_LOG(
"[WIFI_MANAGER] init failed: wifi already on\n"
);
return -1;
}
memset(
&wifi_manager_status_data,
0,
sizeof(wifi_manager_status_data)
);
memset(
wifi_manager_target_ssid,
0,
sizeof(wifi_manager_target_ssid)
);
memset(
wifi_manager_target_password,
0,
sizeof(wifi_manager_target_password)
);
wifi_manager_target_valid = 0;
/*
* 与 AC79NN 官方 demo_wifi 的启动顺序保持一致:
* 在注册 callback / wifi_on() 之前先设置 STA 可保存的 SSID 数量。
*/
wifi_set_store_ssid_cnt(5);
wifi_set_event_callback(
wifi_manager_sdk_event_callback
);
/*
* 这里只初始化 manager,不立即 wifi_on()。
*
* 等 wifi_manager_connect() 先拿到目标凭据后再启动 Wi-Fi,
* 这样 MODULE_INIT 才能取得本次目标 STA 信息。
*/
wifi_manager_status_data.initialized = 1;
APP_LOG("[WIFI_MANAGER] init success\n");
return 0;
}
int wifi_manager_connect(
const char *ssid,
const char *password
)
{
size_t ssid_len;
size_t password_len;
int ret;
if (!wifi_manager_status_data.initialized) {
return -1;
}
if (!ssid || !password) {
return -2;
}
ssid_len = strlen(ssid);
password_len = strlen(password);
if (ssid_len == 0 || ssid_len > 32) {
APP_LOG(
"[WIFI_MANAGER] connect failed: invalid ssid len=%u\n",
(unsigned int)ssid_len
);
return -3;
}
if (password_len > 63) {
APP_LOG(
"[WIFI_MANAGER] connect failed: invalid password len=%u\n",
(unsigned int)password_len
);
return -4;
}
memset(
wifi_manager_target_ssid,
0,
sizeof(wifi_manager_target_ssid)
);
memset(
wifi_manager_target_password,
0,
sizeof(wifi_manager_target_password)
);
memcpy(
wifi_manager_target_ssid,
ssid,
ssid_len
);
memcpy(
wifi_manager_target_password,
password,
password_len
);
wifi_manager_target_valid = 1;
wifi_manager_status_data.connecting = 1;
wifi_manager_status_data.sta_associated = 0;
wifi_manager_status_data.network_ready = 0;
/*
* 第一次连接:
* 先保存目标凭据,再启动 Wi-Fi。
*
* wifi_on() 过程中会产生 MODULE_INIT
* callback 在该阶段完成默认 STA 配置。
*/
if (!wifi_is_on()) {
ret = wifi_on();
if (ret != 0) {
wifi_manager_status_data.connecting = 0;
APP_LOG(
"[WIFI_MANAGER] wifi_on failed ret=%d\n",
ret
);
return ret;
}
APP_LOG(
"[WIFI_MANAGER] wifi start/connect submitted ssid=%s\n",
wifi_manager_target_ssid
);
return 0;
}
/*
* Wi-Fi 已经启动后的运行期连接/切换仍使用 wifi_sta。
*/
ret = wifi_sta_connect(
wifi_manager_target_ssid,
wifi_manager_target_password
);
if (ret != 0) {
wifi_manager_status_data.connecting = 0;
APP_LOG(
"[WIFI_MANAGER] runtime connect request failed ret=%d\n",
ret
);
return ret;
}
APP_LOG(
"[WIFI_MANAGER] runtime connect request submitted ssid=%s\n",
wifi_manager_target_ssid
);
return 0;
}
int wifi_manager_get_status(
struct wifi_manager_status *out
)
{
if (!out) {
return -1;
}
*out = wifi_manager_status_data;
return 0;
}
int wifi_manager_is_sta_associated(void)
{
return wifi_manager_status_data.sta_associated ? 1 : 0;
}
int wifi_manager_is_network_ready(void)
{
return wifi_manager_status_data.network_ready ? 1 : 0;
}