315 lines
18 KiB
C
315 lines
18 KiB
C
/**
|
||
* @file events.c
|
||
* @brief 系统事件处理模块 —— WiFi / 网络 / LTE 事件分发与处理
|
||
*
|
||
* 本文件是 TXW82x FPV SDK 的核心事件处理单元,主要包含:
|
||
* - sys_event_hdl() : 全局系统事件处理分发函数(任务上下文,可执行耗时操作)
|
||
* - sys_event_hdl_dhcp() : DHCP 客户端生命周期管理(WiFi 连接后启动 DHCP,DHCP 完成后记录 IP)
|
||
* - sys_event_hdl_lte() : LTE/4G 网卡与 WiFi 之间的网络切换逻辑
|
||
* - sys_wifi_event_cb() : WiFi 协议栈事件回调(在协议栈任务/中断上下文中执行,禁止耗时操作)
|
||
* - sys_wifi_event_hdl_default() : 更新 sys_status 结构体中的 WiFi 状态信息
|
||
*/
|
||
|
||
#include "sys_config.h" // 系统总配置头文件,包含各功能模块的宏开关
|
||
#include "basic_include.h" // 基础头文件集合(os_printf、os_memcpy 等基础 API)
|
||
#include "lib/net/skmonitor/skmonitor.h" // socket 监控库,用于网络连接状态监控
|
||
#include "lib/net/dhcpd/dhcpd.h" // DHCP 服务器端库(本文件未直接使用,但头文件引用保留以备扩展)
|
||
#include "lib/net/uhttpd/uhttpd.h" // 超轻量 HTTP 服务器库(本文件未直接使用,保留以备扩展)
|
||
#include "lib/umac/ieee80211.h" // IEEE 802.11 协议定义(WiFi 事件枚举、模式宏等)
|
||
#include "lib/net/utils.h" // 网络工具函数(如 lwip_netif_set_dhcp2 等)
|
||
#include "lwip/err.h" // LwIP 错误码定义
|
||
#include "lwip/sockets.h" // LwIP BSD socket 兼容层
|
||
#include "lwip/netdb.h" // LwIP 网络数据库函数(gethostbyname 等)
|
||
#include "lwip/sys.h" // LwIP 系统抽象层(线程、信号量等)
|
||
#include "lwip/ip_addr.h" // LwIP IP 地址操作宏(IPSTR、IP2STR_N 等)
|
||
#include "lwip/tcpip.h" // LwIP TCP/IP 协议栈核心接口
|
||
#include "lwip/dns.h" // LwIP DNS 解析接口(dns_getserver 等)
|
||
#include "netif/ethernetif.h" // 以太网网络接口驱动层
|
||
#include "lwip/apps/netbiosns.h" // LwIP NetBIOS 名称服务(本文件未直接使用,保留以备扩展)
|
||
#include "lwip/dns.h" // LwIP DNS 头文件(重复包含,无副作用,保留原始代码不变)
|
||
#include "syscfg.h" // 系统配置持久化存储接口(syscfg_save 等)
|
||
#include "lib/bluetooth/uble/ble_demo.h" // BLE 蓝牙低功耗演示模块(用于蓝牙配网功能)
|
||
#include "sysevt_usb/sysevt_usb.h" // USB 主机事件处理(视频 USB 设备相关)
|
||
|
||
/**
|
||
* @brief WiFi 配对模块的事件处理函数(外部定义)
|
||
* 处理 WiFi 配对(pair)相关的协议栈事件
|
||
*/
|
||
extern int32 sys_wifi_event_hdl_wifi_pair(uint8 ifidx, uint16 evt, uint32 param1, uint32 param2);
|
||
|
||
/**
|
||
* @brief 配对指示灯模块的事件处理函数(外部定义)
|
||
* 根据 WiFi 配对状态控制 LED 指示灯
|
||
*/
|
||
extern int32 sys_wifi_event_hdl_pairled(uint8 ifidx, uint16 evt, uint32 param1, uint32 param2);
|
||
|
||
/**
|
||
* @brief 配对指示灯模块的事件处理函数(重复声明,保留原始代码不变)
|
||
*/
|
||
extern int32 sys_wifi_event_hdl_pairled(uint8 ifidx, uint16 evt, uint32 param1, uint32 param2);
|
||
|
||
/**
|
||
* @brief 对讲机模块的事件处理函数(外部定义)
|
||
* 处理 WiFi 对讲机(walkie-talkie)相关的协议栈事件
|
||
*/
|
||
extern int32 sys_wifi_event_hdl_walkietalkie(uint8 ifidx, uint16 evt, uint32 param1, uint32 param2);
|
||
|
||
/**
|
||
* @brief WiFi 配对的系统事件处理函数(外部定义)
|
||
* 在 sys_event_hdl() 任务上下文中处理配对相关逻辑(可执行耗时操作)
|
||
*/
|
||
extern void sys_event_hdl_wifi_pair(uint32 event_id, uint32 data, uint32 priv);
|
||
|
||
/**
|
||
* @brief 对讲机模块的系统事件处理函数(外部定义)
|
||
* 在 sys_event_hdl() 任务上下文中处理对讲机相关逻辑(可执行耗时操作)
|
||
*/
|
||
extern void sys_event_hdl_walkie_talkie(uint32 event_id, uint32 data, uint32 priv);
|
||
|
||
/**
|
||
* @brief 处理 DHCP 相关系统事件(WiFi 连接后启动 DHCP 客户端,DHCP 完成后保存 IP 信息)
|
||
*
|
||
* 该函数由 sys_event_hdl() 调用,运行在系统事件任务上下文中,可以执行耗时操作。
|
||
* 主要处理两个事件:
|
||
* 1. WiFi 连接成功 → 启动 DHCP 客户端获取 IP 地址
|
||
* 2. DHCP 客户端完成 → 将获取到的 IP/掩码/网关/DNS 保存到 sys_status
|
||
*
|
||
* @param event_id 系统事件 ID,由 SYS_EVENT(模块, 子事件) 宏组合而成
|
||
* @param data 事件附带的数据(本函数未使用)
|
||
* @param priv 事件附带的私有数据(本函数未使用)
|
||
*/
|
||
//更新 sys_status 信息 // Update sys_status information
|
||
static void sys_event_hdl_dhcp(uint32 event_id, uint32 data, uint32 priv)
|
||
{
|
||
switch (event_id) {
|
||
/* WiFi 连接成功事件 */
|
||
case SYS_EVENT(SYS_EVENT_WIFI, SYSEVT_WIFI_CONNECTTED):
|
||
/* 如果配置中启用了 DHCP 客户端,则启动 DHCP 流程获取 IP 地址 */
|
||
if (sys_cfgs.dhcpc_en) {
|
||
sys_status.dhcpc_done = 0; // 清零 DHCP 完成标志,表示正在进行 DHCP
|
||
lwip_netif_set_dhcp2("w0", 1); // 在 "w0"(WiFi 接口)上启动 LwIP DHCP 客户端
|
||
os_printf(KERN_NOTICE"wifi connected, start dhcp client ...\r\n"); // 打印日志:WiFi 已连接,启动 DHCP
|
||
}
|
||
/* 如果当前工作在 STA(Station 站点)模式,则保存当前连接的 AP 信息到持久化配置 */
|
||
if(sys_cfgs.wifi_mode == WIFI_MODE_STA) {
|
||
ieee80211_conf_get_ssid(sys_cfgs.wifi_mode, sys_cfgs.ssid); // 获取当前连接的 SSID 并存入配置
|
||
ieee80211_conf_get_psk(sys_cfgs.wifi_mode, sys_cfgs.psk); // 获取当前连接的 PSK 密码并存入配置
|
||
sys_cfgs.key_mgmt = ieee80211_conf_get_keymgmt(sys_cfgs.wifi_mode); // 获取当前密钥管理方式(WPA/WPA2/Open)
|
||
syscfg_save(); // 将配置持久化保存到 Flash,下次开机自动连接
|
||
}
|
||
break;
|
||
|
||
/* DHCP 客户端完成事件(成功获取到 IP 地址) */
|
||
case SYS_EVENT(SYS_EVENT_NETWORK, SYSEVT_LWIP_DHCPC_DONE): {
|
||
struct netif *nif = netif_find("w0"); // 通过名称 "w0" 查找 WiFi 网络接口的 netif 结构体
|
||
sys_status.dhcpc_done = 1; // 标记 DHCP 过程已完成
|
||
sys_status.dhcpc_result.ipaddr = nif->ip_addr.addr; // 保存 DHCP 分配的 IP 地址
|
||
sys_status.dhcpc_result.netmask = nif->netmask.addr; // 保存 DHCP 分配的子网掩码
|
||
sys_status.dhcpc_result.svrip = 0; // DHCP 服务器 IP 未使用,置零保留
|
||
sys_status.dhcpc_result.router = nif->gw.addr; // 保存 DHCP 分配的默认网关地址
|
||
sys_status.dhcpc_result.dns1 = (dns_getserver(0))->addr; // 保存主 DNS 服务器地址(索引0)
|
||
sys_status.dhcpc_result.dns2 = (dns_getserver(1))->addr; // 保存备用 DNS 服务器地址(索引1)
|
||
os_printf(KERN_NOTICE"dhcp done, ip:"IPSTR", mask:"IPSTR", gw:"IPSTR"\r\n", // 打印获取到的 IP 信息
|
||
IP2STR_N(nif->ip_addr.addr), IP2STR_N(nif->netmask.addr), IP2STR_N(nif->gw.addr));
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 处理 LTE/4G 网卡与 WiFi 之间的网络切换事件
|
||
*
|
||
* 当系统同时具备 WiFi 和 LTE(通过 USB RNDIS 网卡)两种网络通路时,
|
||
* 本函数实现优先级切换策略:WiFi 优先,WiFi 断开时回退到 LTE。
|
||
*
|
||
* 切换逻辑:
|
||
* - LTE 连接且 WiFi 未连接 → 使用 LTE 作为默认网口,启动 LTE 上的 DHCP
|
||
* - WiFi 连接成功 → 关闭 LTE 网口,切换默认网口为 WiFi(WiFi 优先)
|
||
* - WiFi 断开 → 重新启用 LTE 网口,回退到 LTE 网络
|
||
*
|
||
* @param event_id 系统事件 ID
|
||
* @param data 事件附带的数据(本函数未使用)
|
||
* @param priv 事件附带的私有数据(本函数未使用)
|
||
*/
|
||
void sys_event_hdl_lte(uint32 event_id, uint32 data, uint32 priv)
|
||
{
|
||
#if defined(RT_USBH_WIRELESS_RNDIS) && !defined(STATIC_RNDIS_NETDEV)
|
||
// 只在启用了RNDIS功能且是动态申请网口时才需要事件进行切换
|
||
// Only when RNDIS feature is enabled and netdev is dynamically allocated, event-based switching is needed
|
||
switch (event_id) {
|
||
/* LTE 网卡连接事件(USB RNDIS 网卡已就绪) */
|
||
case SYS_EVENT(SYS_EVENT_LTE, SYSEVT_LTE_CONNECTED):
|
||
os_printf("lte connected\r\n"); // 打印日志:LTE 已连接
|
||
if (sys_status.wifi_connected == 0) { // 如果 WiFi 当前未连接,则使用 LTE 作为默认网络
|
||
lwip_netif_set_default2("l0"); // 将 "l0"(LTE 网口)设置为 LwIP 默认路由接口
|
||
lwip_netif_set_dhcp2("l0", 1); // 在 LTE 网口上启动 DHCP 客户端获取 IP
|
||
os_printf("start dhcp client on l0 ...\r\n"); // 打印日志:在 LTE 接口启动 DHCP
|
||
}
|
||
break;
|
||
/* WiFi 连接成功事件 —— WiFi 优先级高于 LTE,关闭 LTE 网口 */
|
||
case SYS_EVENT(SYS_EVENT_WIFI, SYSEVT_WIFI_CONNECTTED):
|
||
lwip_netif_updown2("l0", 0); // 关闭 "l0"(LTE 网口),参数0表示 down
|
||
lwip_netif_set_default2("w0"); // 将 "w0"(WiFi 网口)设为默认路由接口
|
||
os_printf("wifi connected, down lte netif ...\r\n"); // 打印日志:WiFi 已连接,关闭 LTE
|
||
break;
|
||
/* WiFi 断开事件 —— 回退到 LTE 网络 */
|
||
case SYS_EVENT(SYS_EVENT_WIFI, SYSEVT_WIFI_DISCONNECT):
|
||
lwip_netif_updown2("l0", 1); // 重新启用 "l0"(LTE 网口),参数1表示 up
|
||
lwip_netif_set_default2("l0"); // 将默认路由切回 LTE 网口
|
||
os_printf("wifi disconnected, up lte netif ...\r\n"); // 打印日志:WiFi 已断开,启用 LTE
|
||
break;
|
||
}
|
||
#endif
|
||
}
|
||
|
||
/**
|
||
* @brief 全局系统事件处理分发函数(系统事件任务上下文入口)
|
||
*
|
||
* 该函数是系统事件处理的核心分发器,由系统事件任务循环调用。
|
||
* 它依次调用各功能模块的事件处理函数,实现事件的广播式分发。
|
||
*
|
||
* 重要特性:
|
||
* - 运行在独立的系统事件任务上下文中,可以执行耗时操作(如 DHCP、Flash 读写)
|
||
* - 返回 SYSEVT_CONTINUE 表示事件继续传递给后续处理函数(不截断事件)
|
||
* - 简单功能可直接在此函数中调用处理 API,复杂功能建议通过 sys_event_take() 注册独立处理函数
|
||
*
|
||
* @param event_id 系统事件 ID,由 SYS_EVENT(模块, 子事件) 宏组合而成
|
||
* @param data 事件附带的数据
|
||
* @param priv 事件附带的私有数据
|
||
* @return sysevt_hdl_res 返回 SYSEVT_CONTINUE 表示事件继续传递
|
||
*/
|
||
sysevt_hdl_res sys_event_hdl(uint32 event_id, uint32 data, uint32 priv)
|
||
{
|
||
#if SYS_WIFI_PAIR
|
||
sys_event_hdl_wifi_pair(event_id, data, priv); // WiFi 配对功能的事件处理
|
||
#endif
|
||
|
||
#ifdef SYS_APP_WALKIE_TALKIE
|
||
sys_event_hdl_walkie_talkie(event_id, data, priv); // 对讲机功能的事件处理
|
||
#endif
|
||
/*
|
||
* 继续添加其他模块的处理函数 ...
|
||
* Continue adding other module handlers ...
|
||
* 一些小功能的事件处理没必要使用 sys_event_take,在此添加API调用即可。
|
||
* Small features can simply add API calls here without using sys_event_take.
|
||
* 复杂功能的事件处理,可以使用 sys_event_take API 注册事件处理函数。
|
||
* Complex features can use sys_event_take API to register event handlers.
|
||
* 使用 sys_event_take 注册,每次会消耗16byte heap memory
|
||
* Each sys_event_take registration consumes 16 bytes of heap memory
|
||
*/
|
||
#if SYS_APP_BLENC
|
||
sys_event_ble_netconfig(event_id, data, priv); // BLE 蓝牙配网功能的事件处理
|
||
#endif
|
||
|
||
sys_event_hdl_dhcp(event_id, data, priv); // DHCP 客户端生命周期管理
|
||
sys_event_hdl_lte(event_id, data, priv); // LTE/WiFi 网络切换处理
|
||
|
||
system_event_usbh_video_hdl(event_id, data, priv); // USB 主机视频设备事件处理
|
||
|
||
return SYSEVT_CONTINUE; // 返回"继续传递",不截断事件,让后续处理函数也能收到该事件
|
||
}
|
||
|
||
/**
|
||
* @brief WiFi 协议栈事件默认处理函数 —— 更新 sys_status 结构体中的 WiFi 状态
|
||
*
|
||
* 该函数在 sys_wifi_event_cb() 中被调用,负责将 WiFi 协议栈上报的事件
|
||
* 转换为 sys_status 结构体中的状态字段更新,供应用层查询当前 WiFi 状态。
|
||
*
|
||
* @param ifidx WiFi 接口索引(0=w0, 1=w1)
|
||
* @param evt WiFi 协议栈事件类型(IEEE80211_EVENT_xxx)
|
||
* @param param1 事件参数1(具体含义取决于事件类型)
|
||
* @param param2 事件参数2(具体含义取决于事件类型)
|
||
* @return int32 固定返回 0
|
||
*/
|
||
//更新 sys_status 信息 // Update sys_status information
|
||
static int32 sys_wifi_event_hdl_default(uint8 ifidx, uint16 evt, uint32 param1, uint32 param2)
|
||
{
|
||
switch (evt) {
|
||
/* WiFi 连接成功事件 */
|
||
case IEEE80211_EVENT_CONNECTED:
|
||
sys_status.wifi_connected = 1; // 标记 WiFi 已连接
|
||
sys_status.wifi_status_code = 0; // 连接状态码清零(0 = 成功)
|
||
sys_status.channel = ieee80211_conf_get_channel(WIFI_MODE_STA); // 获取当前工作信道号
|
||
os_memcpy(sys_status.bssid, param1, 6); // 拷贝 AP 的 MAC 地址(BSSID,6字节)到状态结构体
|
||
break;
|
||
/* RSSI(接收信号强度指示)更新事件 */
|
||
case IEEE80211_EVENT_RSSI:
|
||
sys_status.rssi = (int8)param1; // 将最新的 RSSI 值(有符号8位,单位 dBm)保存到状态
|
||
break;
|
||
/* EVM(误差向量幅度)更新事件,反映信号调制质量 */
|
||
case IEEE80211_EVENT_EVM:
|
||
sys_status.evm = (int8)param1; // 将最新的 EVM 值保存到状态,值越小信号质量越好
|
||
break;
|
||
/* WiFi 连接失败事件 */
|
||
case IEEE80211_EVENT_CONNECT_FAIL:
|
||
sys_status.wifi_connected = 0; // 标记 WiFi 未连接
|
||
sys_status.wifi_status_code = param2; // 保存失败原因状态码,用于诊断连接失败原因
|
||
break;
|
||
/* WiFi 断开连接事件 */
|
||
case IEEE80211_EVENT_DISCONNECTED:
|
||
sys_status.wifi_connected = 0; // 标记 WiFi 未连接
|
||
sys_status.wifi_reason_code = param2; // 保存断开原因码(如 beacon 超时、AP 主动断开等)
|
||
break;
|
||
/* WiFi 接口使能(启用)事件 */
|
||
case IEEE80211_EVENT_INTERFACE_ENABLE:
|
||
sys_status.wifi_mode = param1; // 记录当前 WiFi 工作模式(STA/AP/MONITOR 等)
|
||
break;
|
||
/* 信道切换事件(可能由 DFS 雷达检测触发,或手动切换信道) */
|
||
case IEEE80211_EVENT_CHANNEL_CHANGE:
|
||
sys_status.channel = param2; // 更新当前工作信道号到状态结构体
|
||
sys_cfgs.channel = param2; // 同步更新配置中的信道号(可能是 DFS 信道切换)
|
||
break;
|
||
default:
|
||
break; // 未处理的事件类型,忽略
|
||
}
|
||
|
||
return 0; // 返回 0,表示处理完成
|
||
}
|
||
|
||
/**
|
||
* @brief WiFi 协议栈事件回调函数 —— 在协议栈任务上下文中执行的入口
|
||
*
|
||
* 该函数由 WiFi 协议栈在事件发生时直接调用,运行在协议栈任务(或中断)上下文中。
|
||
*
|
||
* 【重要约束】由于运行在协议栈任务上下文:
|
||
* - 禁止执行耗时操作(如 DHCP 流程、Flash 读写、长循环等)
|
||
* - 只能做轻量级操作(更新状态变量、设置标志位、发送信号量等)
|
||
* - 需要执行耗时逻辑时,应通过 sys_event_post() 将事件转发到 sys_event_hdl() 处理
|
||
*
|
||
* 各子处理函数的返回值通过位或(|=)合并,用于向协议栈返回处理结果。
|
||
*
|
||
* @param ifidx WiFi 接口索引(0=w0, 1=w1)
|
||
* @param evt WiFi 协议栈事件类型(IEEE80211_EVENT_xxx)
|
||
* @param param1 事件参数1(如 BSSID 指针、RSSI 值等)
|
||
* @param param2 事件参数2(如原因码、状态码等)
|
||
* @return int32 各子处理函数返回值的位或结果
|
||
*/
|
||
//WiFi协议栈的事件回调函数 // WiFi protocol stack event callback function
|
||
// 该callback是在WiFi协议栈的Task中执行,因此该callback中不能执行耗时的代码
|
||
// This callback executes in the WiFi protocol stack Task, so time-consuming code is not allowed
|
||
// 耗时的代码逻辑,可以使用sys_event_hdl来执行
|
||
// Time-consuming logic should be dispatched to sys_event_hdl for execution
|
||
int32 sys_wifi_event_cb(uint8 ifidx, uint16 evt, uint32 param1, uint32 param2)
|
||
{
|
||
int32 ret = 0; // 初始化返回值为 0,后续通过位或累加各子处理函数的结果
|
||
|
||
#if SYS_WIFI_PAIR
|
||
ret |= sys_wifi_event_hdl_wifi_pair(ifidx, evt, param1, param2); // WiFi 配对功能处理
|
||
#endif
|
||
|
||
#if SYS_WIFI_PAIRLED
|
||
ret |= sys_wifi_event_hdl_pairled(ifidx, evt, param1, param2); // 配对指示灯功能处理
|
||
#endif
|
||
|
||
#ifdef SYS_APP_WALKIE_TALKIE
|
||
ret |= sys_wifi_event_hdl_walkietalkie(ifidx, evt, param1, param2); // 对讲机功能处理
|
||
#endif
|
||
/*
|
||
* 继续添加其他模块的处理函数 ...
|
||
* Continue adding other module handlers ...
|
||
*/
|
||
|
||
ret |= sys_wifi_event_hdl_default(ifidx, evt, param1, param2); // 默认处理:更新 sys_status 状态
|
||
return ret; // 返回合并后的处理结果
|
||
}
|