#include "system/includes.h" #include #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; }