feat(launcher): 蓝牙/WiFi 独立子页面(安卓风)— 新增 subpage.c 统一脚手架(顶栏+分组列表+跟手滚动+左缘返回) + wifi_page.c(开关/当前连接详情/已保存/附近,BSSID去重+中文SSID) + bt_page.c(开关/已连接/已配对/附近扫描配对);SMENU 网络组收敛为 2 入口行 (agent-178)
launcher bd37c8b0→d10c0e8a; 改动文件 -Wall -Wextra 0 warning; 真机待验证: 蓝牙 pair/connect、开关联动、触摸几何 出入: 中文SSID/BSSID去重复用 net.c 既有实现; 模态复用 s_dd_modal(SDK 模态层未上收, 未改 SDK); s_net_open 旧分支留作死代码未删
This commit is contained in:
1 parent
366bf6bb5d
commit
f2786552d5
10 files changed
+1122
-86
No files matched your search
@@ -59,7 +59,7 @@ int proc_by_comm(const char *target)
|
||||
|
||||
static char g_bt_mode[48] = "开启未连接"; /* 设置页"蓝牙模式"行展示(bt_role_refresh 刷新) */
|
||||
|
||||
static int bt_role(char *desc, int len); /* 前向声明;实现在网络段(用 popen 带超时) */
|
||||
int bt_role(char *desc, int len); /* 前向声明;实现在网络段(用 popen 带超时),跨模块给 bt_page 用 */
|
||||
|
||||
|
||||
/* ===== M2.39/M2.40 网络/WiFi/蓝牙(设置页「网络」分组)=====
|
||||
@@ -186,7 +186,7 @@ void net_wifi_ssid(char *buf, int len)
|
||||
* 填充 info[][48](调用方提供的二维缓冲),每行 "标签: 值",返回行数(≤max)。
|
||||
* 当前SSID / AP MAC(bssid) / 本机MAC(address) / AP IP(默认网关) / 本机IP(ip_address) / 频道freq。
|
||||
* 未连接返回 0(调用方显示"未连接")。绝不阻塞:popen 带超时。 */
|
||||
static int net_wifi_info(char (*info)[48], int max)
|
||||
int net_wifi_info(char (*info)[48], int max)
|
||||
{
|
||||
if (!wlan_connected()) return 0;
|
||||
char *o = popen_read_tmo(1500,
|
||||
@@ -217,8 +217,8 @@ static int net_wifi_info(char (*info)[48], int max)
|
||||
|
||||
|
||||
/* 已保存网络(wpa_cli -i wlan0 list_networks):首行为表头,其余每行 "<id>\t<ssid>\t<bssid>\t<flag>"。
|
||||
* 填 out[i].id/.name(SSID,中文经 wpa_decode_ssid 还原 \xNN),返回项数(≤max)。 */
|
||||
static int net_wifi_saved(meow_net_t *out, int max)
|
||||
* 填 out[i].id/.name(SSID,中文经 wpa_decode_ssid 还原 \xNN)/.mac(BSSID),返回项数(≤max)。 */
|
||||
int net_wifi_saved(meow_net_t *out, int max)
|
||||
{
|
||||
int n = 0;
|
||||
char *o = popen_read_tmo(1500, "PATH=/bin:/sbin:/usr/bin:/usr/sbin wpa_cli -i wlan0 list_networks 2>/dev/null");
|
||||
@@ -234,6 +234,9 @@ static int net_wifi_saved(meow_net_t *out, int max)
|
||||
char *sp = p; while (*sp && *sp != ' ' && *sp != '\t') sp++;
|
||||
while (*sp == ' ' || *sp == '\t') sp++;
|
||||
char *se = sp; while (*se && *se != ' ' && *se != '\t' && *se != '\n' && *se != '\r') se++;
|
||||
/* BSSID 列(SSID 后):<id>\t<ssid>\t<bssid>\t<flag>,拷进 mac 供详情/连接展示 */
|
||||
char *bp = se; while (*bp == ' ' || *bp == '\t') bp++;
|
||||
char *be = bp; while (*be && *be != ' ' && *be != '\t' && *be != '\n' && *be != '\r') be++;
|
||||
if (sp != se) {
|
||||
/* M2.40:list_networks 对中文 SSID 输出 \xNN 转义文字(如 \xe5\xa4\xa9… = "天…"),
|
||||
* 先拷进临时缓冲再还原成真实 UTF-8 字节存入 name,否则界面显示超长乱码。 */
|
||||
@@ -243,6 +246,10 @@ static int net_wifi_saved(meow_net_t *out, int max)
|
||||
memcpy(raw, sp, (size_t)l); raw[l] = 0;
|
||||
out[n].id = id;
|
||||
wpa_decode_ssid(raw, out[n].name, sizeof out[n].name);
|
||||
if (be > bp && (be - bp) < (int)sizeof out[n].mac) {
|
||||
memcpy(out[n].mac, bp, (size_t)(be - bp));
|
||||
out[n].mac[be - bp] = 0;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
}
|
||||
@@ -255,7 +262,7 @@ static int net_wifi_saved(meow_net_t *out, int max)
|
||||
|
||||
/* WiFi 扫描触发(异步:wpa_cli scan 只是通知 supplicant 发起扫描,立即返回)。
|
||||
* 结果稍后经 net_wifi_scan() 读。 */
|
||||
static void net_wifi_scan_trigger(void)
|
||||
void net_wifi_scan_trigger(void)
|
||||
{
|
||||
if (!wlan_connected()) return;
|
||||
system("PATH=/bin:/sbin:/usr/bin:/usr/sbin wpa_cli -i wlan0 scan 2>/dev/null");
|
||||
@@ -267,8 +274,8 @@ static void net_wifi_scan_trigger(void)
|
||||
* flags 恒以 '[' 起;SSID 为 flags 后的整段余量(可含空格;为空=隐藏网络)。
|
||||
* M2.40:同一 AP 常出现多条(不同频段/空 SSID/重名),按 BSSID 去重——每个 BSSID 只留一条,
|
||||
* 优先采用含完整 SSID 的行(后到且有 SSID 则覆盖先到的空 SSID 行),隐藏网络显示 "(隐藏网络)"。
|
||||
* 填 out[i].id=-1;name 存 SSID(或隐藏标记)。返回项数(≤max,且 ≤S_NET_MAX)。 */
|
||||
static int net_wifi_scan(meow_net_t *out, int max)
|
||||
* 填 out[i].id=-1;name 存 SSID(或隐藏标记)/mac 存 BSSID。返回项数(≤max,且 ≤S_NET_MAX)。 */
|
||||
int net_wifi_scan(meow_net_t *out, int max)
|
||||
{
|
||||
int n = 0;
|
||||
if (max > S_NET_MAX) max = S_NET_MAX;
|
||||
@@ -315,6 +322,7 @@ static int net_wifi_scan(meow_net_t *out, int max)
|
||||
seen_bssid[idx][sizeof seen_bssid[idx] - 1] = 0;
|
||||
named[idx] = has;
|
||||
out[idx].id = -1;
|
||||
snprintf(out[idx].mac, sizeof out[idx].mac, "%s", bssid); /* 保留 BSSID 供详情展示 */
|
||||
if (has) {
|
||||
/* M2.41:扫描结果 SSID 也可能是 wpa_cli 的 \xNN 转义(中文),还原成真 UTF-8 */
|
||||
char raw[96];
|
||||
@@ -341,8 +349,8 @@ static int net_wifi_scan(meow_net_t *out, int max)
|
||||
|
||||
|
||||
/* 蓝牙已配对设备(bluetoothctl paired-devices):每行 "Device <MAC> <Name>"。
|
||||
* hci 未上电则返回 0(避免 spawn bluetoothctl 白跑)。 */
|
||||
static int net_bt_paired(meow_net_t *out, int max)
|
||||
* 填 out[i].mac=MAC / .name=名称;hci 未上电则返回 0(避免 spawn bluetoothctl 白跑)。 */
|
||||
int net_bt_paired(meow_net_t *out, int max)
|
||||
{
|
||||
if (!hci_powered()) return 0;
|
||||
int n = 0;
|
||||
@@ -358,11 +366,15 @@ static int net_bt_paired(meow_net_t *out, int max)
|
||||
char *mac = p; while (*mac && *mac != ' ' && *mac != '\t') mac++;
|
||||
char *nm = mac; while (*nm == ' ' || *nm == '\t') nm++;
|
||||
/* 设备名每行即名称 token;名称可含空格,这里取整行剩余部分(含 MAC 后的名字) */
|
||||
int ml = (int)(mac - p); if (ml > 47) ml = 47;
|
||||
if (ml > 0 && ml < (int)sizeof out[n].mac) {
|
||||
memcpy(out[n].mac, p, (size_t)ml); out[n].mac[ml] = 0;
|
||||
}
|
||||
if (*nm)
|
||||
snprintf(out[n].name, sizeof out[n].name, "%s", nm);
|
||||
else {
|
||||
int ml = (int)(mac - p); if (ml > 47) ml = 47;
|
||||
memcpy(out[n].name, p, (size_t)ml); out[n].name[ml] = 0;
|
||||
int l = ml; if (l > 47) l = 47;
|
||||
memcpy(out[n].name, p, (size_t)l); out[n].name[l] = 0;
|
||||
}
|
||||
out[n].id = -1;
|
||||
n++;
|
||||
@@ -374,6 +386,42 @@ static int net_bt_paired(meow_net_t *out, int max)
|
||||
}
|
||||
|
||||
|
||||
/* 蓝牙已连接设备(bluetoothctl `devices Connected`):每行 "Device <MAC> <Name>"。
|
||||
* M2.76:供蓝牙独立子页面「已连接设备」分组展示。hci 未上电返回 0。 */
|
||||
int net_bt_connected(meow_net_t *out, int max)
|
||||
{
|
||||
if (!hci_powered()) return 0;
|
||||
char *o = popen_read_tmo(1500,
|
||||
"PATH=/bin:/sbin:/usr/bin:/usr/sbin printf 'devices Connected\\nquit\\n' | bluetoothctl 2>/dev/null");
|
||||
if (!o) return 0;
|
||||
int n = 0;
|
||||
char *line = o;
|
||||
while (line && *line && n < max) {
|
||||
char *eol = strchr(line, '\n');
|
||||
if (eol) *eol = 0;
|
||||
char *q = line; while (*q == ' ' || *q == '\t') q++;
|
||||
if (!strncmp(q, "Device ", 7)) {
|
||||
q += 7;
|
||||
char *mac = q; while (*mac && *mac != ' ' && *mac != '\t' && *mac != '\n' && *mac != '\r') mac++;
|
||||
char *nm = mac; while (*nm == ' ' || *nm == '\t') nm++;
|
||||
int ml = (int)(mac - q); if (ml > 47) ml = 47;
|
||||
if (ml > 0 && ml < (int)sizeof out[n].mac) {
|
||||
memcpy(out[n].mac, q, (size_t)ml); out[n].mac[ml] = 0;
|
||||
}
|
||||
char *e = nm; while (*e && *e != '\n' && *e != '\r') e++;
|
||||
*e = 0;
|
||||
if (*nm) snprintf(out[n].name, sizeof out[n].name, "%s", nm);
|
||||
else { int l = ml; if (l > 47) l = 47; memcpy(out[n].name, q, (size_t)l); out[n].name[l] = 0; }
|
||||
out[n].id = -1;
|
||||
n++;
|
||||
}
|
||||
line = eol ? eol + 1 : NULL;
|
||||
}
|
||||
free(o);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
/* ---- 蓝牙附近设备(未配对扫描发现;异步,不阻塞主循环)----
|
||||
* M2.40:用户要的「附近的设备」= 蓝牙扫描发现(含未配对),而不只是已配对。扫描较慢(2-6s),
|
||||
* 故后台有界驱动 bluetoothctl:scan on → sleep 4 → scan off → devices → quit,输出写 /tmp 缓存;
|
||||
@@ -382,7 +430,7 @@ static int net_bt_paired(meow_net_t *out, int max)
|
||||
static long g_bt_scan_ms = 0; /* 最近一次发起扫描的 now_ms();0=从未 */
|
||||
|
||||
|
||||
static void net_bt_scan_trigger(void)
|
||||
void net_bt_scan_trigger(void)
|
||||
{
|
||||
if (!hci_powered()) return;
|
||||
long t = (long)now_ms();
|
||||
@@ -395,7 +443,7 @@ static void net_bt_scan_trigger(void)
|
||||
/* 读蓝牙附近设备缓存:解析 bluetoothctl `devices` 输出("Device <MAC> <Name>",去重;含已配对
|
||||
* 与未配对但已发现的设备)。缓存不存在/为空则退回已配对列表(保证至少展示已知设备)。
|
||||
* 返回项数(≤max,且 ≤S_NET_MAX)。 */
|
||||
static int net_bt_scan(meow_net_t *out, int max)
|
||||
int net_bt_scan(meow_net_t *out, int max)
|
||||
{
|
||||
if (!hci_powered()) return 0;
|
||||
if (max > S_NET_MAX) max = S_NET_MAX;
|
||||
@@ -424,6 +472,9 @@ static int net_bt_scan(meow_net_t *out, int max)
|
||||
char *e = nm; while (*e && *e != '\n' && *e != '\r') e++;
|
||||
*e = 0; /* 去行尾换行 */
|
||||
strncpy(seen[n], dv, (size_t)ml); seen[n][ml] = 0;
|
||||
if (ml < (int)sizeof out[n].mac) {
|
||||
memcpy(out[n].mac, dv, (size_t)ml); out[n].mac[ml] = 0; /* 保留 MAC 供配对/连接 */
|
||||
}
|
||||
if (*nm)
|
||||
snprintf(out[n].name, sizeof out[n].name, "%s", nm);
|
||||
else {
|
||||
@@ -484,7 +535,7 @@ static int a2dp_side(const char *sec)
|
||||
|
||||
|
||||
/* 蓝牙角色:见上方注释。一次 popen 拿 ACL + A2DP + 已连设备名三类信息,避免反复 spawn。 */
|
||||
static int bt_role(char *desc, int len)
|
||||
int bt_role(char *desc, int len)
|
||||
{
|
||||
if (desc && len > 0) desc[0] = 0;
|
||||
if (!g_sys.bt_seen || !hci_powered()) {
|
||||
@@ -575,6 +626,14 @@ void bt_role_refresh(int force)
|
||||
g_sys.bt_on = (g_sys.bt_role != BT_ROLE_OFF) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* M2.76:蓝牙角色中文描述(节流刷新,读缓存 g_bt_mode;供蓝牙子页摘要行,
|
||||
* 避免子页驻留期间每 tick 反复 popen bt_role)。 */
|
||||
void net_bt_mode_str(char *buf, int len)
|
||||
{
|
||||
bt_role_refresh(0);
|
||||
snprintf(buf, len, "%s", g_bt_mode);
|
||||
}
|
||||
|
||||
|
||||
/* 网络信息缓存(绘制路径只读,s_net_refresh 刷新;下拉打开时才重新解析列表) */
|
||||
static char g_net_ssid[64] = "未连接";
|
||||
@@ -616,6 +675,8 @@ int s_net_get(const srow_t *r, char *buf, int len)
|
||||
case NET_LIST_BT_NEARBY: snprintf(buf, len, "%d 台设备", g_net_bt_n); return 0;
|
||||
case NET_LIST_BT_MODE: snprintf(buf, len, "%s", g_bt_mode); return 0;
|
||||
case NET_LIST_ABOUT: snprintf(buf, len, "MeowOS v%s", g_meowos_version); return 0;
|
||||
case NET_LIST_WIFI_PAGE: snprintf(buf, len, "%s", g_net_ssid); return 0; /* M2.76:子页入口摘要 */
|
||||
case NET_LIST_BT_PAGE: snprintf(buf, len, "%s", g_bt_mode); return 0; /* M2.76 */
|
||||
}
|
||||
snprintf(buf, len, "-");
|
||||
return 0;
|
||||
|
||||
Reference in new issue
Block a user