Files
TAIXIN/project/events.c

315 lines
18 KiB
C
Raw 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.

/**
* @file events.c
* @brief 系统事件处理模块 —— WiFi / 网络 / LTE 事件分发与处理
*
* 本文件是 TXW82x FPV SDK 的核心事件处理单元,主要包含:
* - sys_event_hdl() : 全局系统事件处理分发函数(任务上下文,可执行耗时操作)
* - sys_event_hdl_dhcp() : DHCP 客户端生命周期管理WiFi 连接后启动 DHCPDHCP 完成后记录 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
}
/* 如果当前工作在 STAStation 站点)模式,则保存当前连接的 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 网口,切换默认网口为 WiFiWiFi 优先)
* - 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 地址BSSID6字节到状态结构体
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; // 返回合并后的处理结果
}