From 249b6224ab299553bee4849d6e2a81bce29fc0b9 Mon Sep 17 00:00:00 2001 From: MeowOS Date: Mon, 31 Aug 2026 15:32:13 +0800 Subject: [PATCH] =?UTF-8?q?feat(route):=20meow=5Froute=20=E9=9F=B3?= =?UTF-8?q?=E9=A2=91=E8=BE=93=E5=87=BA=E8=B7=AF=E7=94=B1=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E8=B7=9F=E9=9A=8F=E6=8F=92=E5=AD=94=20(agent-220)=20=E2=80=94?= =?UTF-8?q?=20svcd=E6=89=98=E7=AE=A1,1s=E8=BD=AE=E8=AF=A2switch=20state,4.?= =?UTF-8?q?4=E4=BC=98=E5=85=88;=20=E5=8F=AA=E5=86=99=E5=8F=98=E5=8C=96+?= =?UTF-8?q?=E8=AF=BB=E5=9B=9E=E6=A0=A1=E9=AA=8C+=E4=B8=8D=E9=87=8D?= =?UTF-8?q?=E8=AF=95=E9=A3=8E=E6=9A=B4;=20=E7=9C=9F=E6=9C=BA=E5=B7=B2?= =?UTF-8?q?=E9=83=A8=E7=BD=B2=E8=BF=90=E8=A1=8C(svcd=20tf=20conf)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit meow_route fa2b80be; 主机模拟状态机全过+真机cset/cget往返验证; 物理插拔端到端待用户插耳机实测 注: 223 拼音IME设计稿已出(devdocs/plan/IME_PINYIN_DESIGN.md, 静态表方案~272KB, qemu验证通过) --- patch_v2/meow_route/build_route.sh | 28 ++ patch_v2/meow_route/meow_route | Bin 0 -> 73772 bytes patch_v2/meow_route/meow_route.c | 278 ++++++++++++++++++ patch_v2/meow_route/meow_route_host | Bin 0 -> 72128 bytes .../meow_route/services.d/meow_route.conf | 16 + 5 files changed, 322 insertions(+) create mode 100755 patch_v2/meow_route/build_route.sh create mode 100755 patch_v2/meow_route/meow_route create mode 100644 patch_v2/meow_route/meow_route.c create mode 100755 patch_v2/meow_route/meow_route_host create mode 100644 patch_v2/meow_route/services.d/meow_route.conf diff --git a/patch_v2/meow_route/build_route.sh b/patch_v2/meow_route/build_route.sh new file mode 100755 index 0000000..0c3916a --- /dev/null +++ b/patch_v2/meow_route/build_route.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# build_route.sh — meow_route 交叉编译(mipsel 静态)+ 宿主编译可选。 +# +# 目标:R3 Pro II / MeowOS(mipsel-linux-muslsf,静态)。仅 POSIX + Linux 基接口, +# 无 launcher/IPC 依赖(不链 meow_ipc.h),单文件、体积小。 +# +# 用法: +# ./build_route.sh # 交叉编译 → patch_v2/meow_route/meow_route(mipsel 静态) +# ./build_route.sh host # 宿主编译 → patch_v2/meow_route/meow_route_host +set -e +cd "$(dirname "$0")" +ROOT="$HOME/Project/R3ProII" +CC="$ROOT/.tools/zig-mipsel-cc" + +if [ "$1" = "host" ]; then + HOST_CC="${CC_HOST:-cc}" + "$HOST_CC" -Os -Wall -Wextra meow_route.c -o meow_route_host + echo "== host build ==" + ls -la meow_route_host + file meow_route_host + exit 0 +fi + +"$CC" -Os -Wall -Wextra -static meow_route.c -o meow_route +echo "== meow_route (mipsel static) ==" +ls -la meow_route +md5sum meow_route +file meow_route diff --git a/patch_v2/meow_route/meow_route b/patch_v2/meow_route/meow_route new file mode 100755 index 0000000000000000000000000000000000000000..c26ebac2811a37b1af7ab27e0561a8cccc601ff7 GIT binary patch literal 73772 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 literal 0 HcmV?d00001 diff --git a/patch_v2/meow_route/meow_route.c b/patch_v2/meow_route/meow_route.c new file mode 100644 index 0000000..2300622 --- /dev/null +++ b/patch_v2/meow_route/meow_route.c @@ -0,0 +1,278 @@ +#define _GNU_SOURCE + +/* meow_route.c — MeowOS 音频输出路由自动跟随插孔专项服务。 + * + * 背景:R3 Pro II 有 3.5mm 单端 + 4.4mm 平衡口。输出路由由 ALSA + * `amixer cset numid=9 ` 控制:0=空闲 1=lineout 2=3.5 headset + * 3=4.4 balance 4=Type-C SPDIF(0/5 危险勿写)。插入检测: + * /sys/class/switch/headset/state(3.5)、/sys/class/switch/balance/state(4.4)。 + * MeowOS 若不设路由 → App 播放无声(真机踩过:插 4.4 但路由在 idle=0)。 + * + * 职责:周期(默认 1s,轻量;`--ms` 可覆盖供测试)读两个 switch state; + * 插入变化时自动路由:4.4 → port=3,3.5 → port=2(4.4 优先若同插), + * 都不插 → 不动、保持上次路由。写后 cget 读回校验,失败记日志不重试风暴。 + * + * 双形态: + * - svcd 以**空参**拉起(conf `args=` 空)→ 常驻轮询守护(不 exit,崩溃由 svcd on-fail 收)。 + * - 测试/自检 CLI:`meow_route [--ms M] [--iters N]` 跑 N 轮后退出(N=0 常驻)。 + * + * 测试挂钩(宿主模拟用,默认取真机路径): + * MEOW_AMIXER amixer 可执行(默认 /usr/bin/amixer) + * MEOW_HEADSET_SW 3.5 插孔 switch state 路径 + * MEOW_BALANCE_SW 4.4 平衡 switch state 路径 + * + * 编译(mipsel 静态,仅 POSIX+Linux,无 launcher/IPC 依赖):build_route.sh。 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ROUTE_POLL_MS_DEF 1000 /* 周期轮询,秒级即可(检测 3.5/4.4 插拔) */ +#define AMIXER_TMO_MS 1500 /* amixer 子进程超时,防挂 */ +#define PIPE_MAX 4096 + +/* ALSA Output Port Switch(numid=9)端口值:0=空闲 1=lineout 2=3.5 3=4.4 4=Type-C SPDIF */ +#define CTL_NUMID 9 +#define PORT_BALANCE 3 +#define PORT_HEADSET 2 +#define PORT_NONE (-1) /* 都不插 → 不动、保持上次 */ + +/* 路径通过 env 可覆盖(宿主/模拟测试),默认真机路径 */ +static const char *g_amixer = "/usr/bin/amixer"; +static const char *g_headset = "/sys/class/switch/headset/state"; +static const char *g_balance = "/sys/class/switch/balance/state"; + +static volatile sig_atomic_t g_shutdown = 0; + +/* ---- 日志(走 stderr,supervisor/svcd 捕获;与 meow_svc_perf/power 同纪律) ---- */ +static void svc_log(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "[meow_route] "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +static void on_sig(int sig) +{ + (void)sig; + g_shutdown = 1; +} + +/* ---- 读单个 switch 文件(0/1=插孔状态,-1=读失败) ---- */ +static int read_switch(const char *path) +{ + char buf[32]; + int fd = open(path, O_RDONLY); + if (fd < 0) return -1; + ssize_t n = read(fd, buf, sizeof buf - 1); + close(fd); + if (n <= 0) return -1; + buf[n] = 0; + return atoi(buf); +} + +/* ---- popen 限时读(fork+exec+非阻塞 poll,杀子进程防挂) ---- */ +static char *popen_read_tmo(int tmo_ms, const char *cmd) +{ + int p[2]; + if (pipe(p) < 0) return NULL; + pid_t pid = fork(); + if (pid < 0) { close(p[0]); close(p[1]); return NULL; } + if (pid == 0) { dup2(p[1], 1); close(p[0]); close(p[1]); execl("/bin/sh", "sh", "-c", cmd, (char *)0); _exit(127); } + close(p[1]); + fcntl(p[0], F_SETFL, fcntl(p[0], F_GETFL, 0) | O_NONBLOCK); + char *buf = malloc(PIPE_MAX); + if (!buf) { close(p[0]); waitpid(pid, NULL, 0); return NULL; } + size_t off = 0; + int remain = tmo_ms; + while (remain > 0 && off < PIPE_MAX - 1) { + struct pollfd pf = { p[0], POLLIN, 0 }; + int r = poll(&pf, 1, remain); + if (r < 0) { if (errno == EINTR) { if (g_shutdown) break; continue; } break; } + if (r == 0) break; + ssize_t rd = read(p[0], buf + off, PIPE_MAX - 1 - off); + if (rd == 0) break; + if (rd < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) continue; break; } + off += (size_t)rd; + } + close(p[0]); + waitpid(pid, NULL, 0); + buf[off] = 0; + return buf; +} + +/* 从 `amixer cget` 输出解析当前 port 值。cget 有两处 "values=": + * 首行元数据 `values=1`(数量),末行 `: values=<当前值>`——取末行。 */ +static int parse_amixer_value(const char *out) +{ + if (!out) return -1; + const char *ln = out; + while (ln && *ln) { + const char *nl = strchr(ln, '\n'); + const char *p = ln; + while (*p == ' ' || *p == '\t') p++; + if (p[0] == ':' && strncmp(p, ": values=", 9) == 0) { + return atoi(p + 9); + } + if (!nl) break; + ln = nl + 1; + } + return -1; +} + +/* 读当前输出端口(numid=9);读失败/解析失败返回 -1 */ +static int amixer_get_port(void) +{ + char cmd[160]; + snprintf(cmd, sizeof cmd, "%s cget numid=%d 2>/dev/null", g_amixer, CTL_NUMID); + char *out = popen_read_tmo(AMIXER_TMO_MS, cmd); + if (!out) return -1; + int v = parse_amixer_value(out); + free(out); + return v; +} + +/* 发出 cset 写(输出仅参考,权威以 cget 读回为准);执行失败返回 -1 */ +static int amixer_set_port(int port) +{ + char cmd[160]; + snprintf(cmd, sizeof cmd, "%s cset numid=%d %d 2>/dev/null", g_amixer, CTL_NUMID, port); + char *out = popen_read_tmo(AMIXER_TMO_MS, cmd); + if (!out) return -1; + free(out); + return 0; +} + +static const char *port_name(int port) +{ + switch (port) { + case PORT_BALANCE: return "4.4 balance"; + case PORT_HEADSET: return "3.5 headset"; + default: return "idle"; + } +} + +/* 一次评估:读两 switch,若(有插入且状态变化或与上次处理目标不同)则写路由并读回校验。 + * last_hb/last_bal 为上次观测记忆(evaluate 内更新,仅成功读才更新;初始 -1, + * 首次强制评估 → 覆盖"开机即已插"场景)。 + * last_target = 上次对当前插孔态**决策过**的目标端口(成功/已接/失败都记), + * 状态不变时不重复尝试 → 满足"写失败不重试风暴"。 */ +static void evaluate(int *last_hb, int *last_bal, int *last_target) +{ + int hb = read_switch(g_headset); + int bal = read_switch(g_balance); + + /* 读失败:未知状态,不动端口,不更新记忆,待下轮重试(防误路由) */ + if (hb < 0 || bal < 0) { + svc_log("switch read err: headset=%d balance=%d (skip this cycle)", hb, bal); + return; + } + int prev_hb = *last_hb, prev_bal = *last_bal; + *last_hb = hb; + *last_bal = bal; + + int target; + if (bal == 1) target = PORT_BALANCE; /* 4.4 优先(同插) */ + else if (hb == 1) target = PORT_HEADSET; + else target = PORT_NONE; + + if (target == PORT_NONE) { + /* 都不插 → 不动、保持上次。日志仅在状态翻转时给一次,避免每秒刷屏 */ + if (prev_hb != hb || prev_bal != bal) + svc_log("no jack (headset=%d balance=%d), keep last port", hb, bal); + *last_target = PORT_NONE; + return; + } + + int changed = (prev_hb != hb || prev_bal != bal); + if (!changed && *last_target == target) { + /* 状态未变且上次已决策过该目标(成功/已接/失败)→ 不再写,防重试/cset 风暴 */ + return; + } + + int cur = amixer_get_port(); + if (cur == target) { + /* 路由已是目标(如上次设置成功/开机偶合),无需写 */ + svc_log("%s already routed (port=%d)", port_name(target), cur); + *last_target = target; + return; + } + + svc_log("jack changed -> routing to %s (wanted %d, was %d)", + port_name(target), target, cur); + if (amixer_set_port(target) < 0) { + svc_log("amixer cset exec failed (wanted %d)", target); + *last_target = target; /* 状态不变不再重试 */ + return; + } + int rb = amixer_get_port(); + if (rb == target) { + svc_log("routed ok: numid=9 -> %d (%s)", rb, port_name(target)); + } else { + /* 读回不符:记日志,不重试(下次同状态不再写;状态翻身后才再评估) */ + svc_log("route verify failed: wanted %d got %d (no retry)", target, rb); + } + *last_target = target; +} + +int main(int argc, char **argv) +{ + /* 测试挂钩:env 覆盖路径 */ + const char *e; + if ((e = getenv("MEOW_AMIXER")) && e[0]) g_amixer = e; + if ((e = getenv("MEOW_HEADSET_SW")) && e[0]) g_headset = e; + if ((e = getenv("MEOW_BALANCE_SW")) && e[0]) g_balance = e; + + int poll_ms = ROUTE_POLL_MS_DEF; + long iters = 0; /* 0=常驻 */ + for (int i = 1; i < argc; i++) { + if (!strcmp(argv[i], "--ms") && i + 1 < argc) { poll_ms = atoi(argv[++i]); if (poll_ms < 50) poll_ms = 50; } + else if (!strcmp(argv[i], "--iters") && i + 1 < argc) { iters = atol(argv[++i]); if (iters < 0) iters = 0; } + else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { + printf("meow_route [--ms MS] [--iters N] (默认常驻轮询; N>0 跑 N 轮后退出)\n"); + return 0; + } + } + + signal(SIGPIPE, SIG_IGN); + signal(SIGTERM, on_sig); + signal(SIGINT, on_sig); + + int last_hb = -1, last_bal = -1, last_target = PORT_NONE; + + svc_log("start: numid=%d poll_ms=%d amixer=%s", CTL_NUMID, poll_ms, g_amixer); + + long cycles = 0; + for (;;) { + evaluate(&last_hb, &last_bal, &last_target); + + if (iters > 0 && ++cycles >= iters) break; + if (g_shutdown) break; + + /* 分段睡眠以即时响应 SIGTERM */ + int naps = poll_ms / 200; + if (naps < 1) naps = 1; + for (int k = 0; k < naps; k++) { + if (g_shutdown) break; + struct timespec ts = { 0, 200 * 1000000L }; + nanosleep(&ts, NULL); + } + if (g_shutdown) break; + } + + svc_log("exit (iters=%ld)", iters); + return 0; +} diff --git a/patch_v2/meow_route/meow_route_host b/patch_v2/meow_route/meow_route_host new file mode 100755 index 0000000000000000000000000000000000000000..8de221386ff0d34ec802d80a992627defd227f32 GIT binary patch literal 72128 zcmeHMeRx#WnLjf(Kne)qJ0i*j0Ruun1^m`YVhpr^G{n`4_U2~hCK)rC8E0-FNG+pi z-K{>|jG$7#h^)0HTU%S%R&2LM>aIT8?IKo|ZL2$psQB0qETBXQv%mM=bCNTYxjsJo zJpF6W;kkLw`#bOZp7;FD$GvmdQoZVGzt6`+(b&%zX+4u%B)}U|6NhX9>>@Ur1=yKv z1{;a?B0Rz_UoP>Z5k<&iS7jO``EBRz`SJ{IC#2||T1vQKE$`2Z&p78%NHKrZ?_@mG zT(jm{w(rLWV^@Cf;UBy(bJdAgpKZMDwYlFpwm1@QSR4s0iiD$W?Tbt^5o}(*v^*Ir zKhK>NiY4Nq`h|;zRa<)6aC41K1t=!cZT~XF#NnpwMGw5u18?`h*J1!V+VV>WfZ6#V z^w01V%I8@R{F}fh;K?rw0Thb!vIqVf5BypW{00wvtp|RN2Tl`QD9_~{_G3Kor#*1f z1CMyjOEK_5d>;3Rv)2QE%LAwFT4=oJwjjRK1Ha1ypXGsLOBIY??SXIh;OCHs{gWQ} z9uJ&F&1ftcv8*^VjHGP_TZ~|Hi_vI?BdjrDS*$S_wIeJZi$IShT3Es|LonUY7*B+w zb|YD{P+R{7MK`cuB$h-*@isfiHkx5O9u7HLk|o1U@Sq_? zrM$?yl?H}RqA>&Mn07dZ{2F2jo5jO%r-P_#Gc@?7HZu`olrbHG%UR*0v1ZlE$|~dh z^7AfaqI$tnW~{7RZD3GVQ#ff`iMrKQkyzBKGaDin@@Q&}ML7$GYg*6{b4A6Ef0}bn zQtk8p(R-;-yBmW}S|9$+!CIpCiH_&N^aFSe6|qZzQSrflI&UX^x6`h%YL2<~{y}^3 z9@qGbEkiFElpXwiE%19eekAL5B=FRD*S;A2QW3b&OY-oq@b_zJ9)2#z^*nqG$6w+7 z`jF=+w@c^mJ_#4!5Y%u`!s(0?B_rXb0)#v);ipUZ2??Jg;m@6NdGI5j!A~Ew_eeOW z)bV;n!sYLXmZkI_o|AcnpFOhJ*1ReY$37_I1?w^2!)7Ob8D&m+Z)|FAmTa?aLe5Pdo_Y$s4c!z|~lJFf8 zE`JwwO8D85{ZkS?SHho>@OcvcoP^W2h$vT{t-U$0`Gu|ljiq<{*!F?VFFy4GupZ4g zAZ$n;fz1(!2{+XAm+ZYHt@~#ln5k=TipOdDI@h(CdnNsw(EB9)4(R^NhWh^&^x2aBZRnMf{vGHIl71ibJ0$%9 z=({BSA?SN0{W0i$lD-SN|MH>!pM*YJ(z~HoO8O6>H%R(Vpx+_sKZU+a(w~RESJHn8 zy-(8jLib-W)c?OjpDpRHLa&tc-#~AW^!?E9kn{u4cS-v1pzoFRx1smBy1aI%p4CRY zKCpRQ*T7aSeSCdM*T))LkimLl$7=eIt{dO=NpM0}f6K(K&yth6KGS^NJ{IWjjj?_o zOYMjIGc0pX`kid{!A`s)(RQ)P*i!tQ@6d}`ztdh)mi~RA_OZNuZCUz_y!Kx7ua~fX zoG%@j`^wTdPdadRblmVpSvoTce%~)k^nr7)BZKx&Vqj~^w{topSEH&}$F@gR*ZPJ2S zutWYGY~h0Rr?9;od+-x&#sYSFs&>m++ASZWzW!O3t{>eqy_C3kY3FqGzh`L`OQ%K# z`tiNK{V2FhjSlpWK>Zl%^?tTMFFvunPn*1;7kwPlrY$(CO5B!hP6GXv%=e+Q zUQT0mGtj=pKeZ+0zwXw|sGZYyj%2sgBi}8MDUH?jAU4Gk9I+?PO}~w68k!r*dn4wm zp0Q^ml>(nZ~dZCSn}Hxy10^qd58Yvlx4A_Q@@8RE)j-o>?a=w!H}ZKKNFitm$uXeEoyI?mPFF z&O7%g&XS|(vwm0L;((7`h`9UM;hO#we4IY8w=Tw54q`p)v?h14i;rS$3~b&z_@1UQ z5I;EorjZZMqFUcVwukb}ZuPzHi~;*(V6)aW@GF)+x~{0}__?fqHug;4G}iA2XPC>{ zE74EDcVao_W}@(UXIj9q3o`$QWQWiFx@y=R1NVJeYJV^G=5ef*%_xx{#YQ*V!t1H;h7VKIB&1g)^)hoa{^f zxu(DOo(WwJC&>SuZ45%nY)Xg?)%3PPak@4(|xS|VVbH|8z z7})H``;Yk7x*V=(t}(9T>x-}lMszu2z&nNZ6>?3#fH=%|;=+G}B#wJ9HXr{O@R!y76nU!-uExxq0bX z2j`_}A2H(SrFrT5$##6I_HM{m@f?Le)ZPWdr*$NtHP@g&(} zK6Q=lUXJ!s;MD&eKTp*npZ%HjzWEufr6*vQ@t;`!p5u%2qlDdZJGjKyj=8?KJ+Mp$+TL@$bvtzF*TOzgEd6zh?R;-}5}$ z0|VLJJ?z9!Uq+oV^u3VX^7zSY-2wRFzW$z_pI-S<_*1N9=mVQ8yD;YNqwA`0c3p*e zs~%d%Tea8e%og)OXZFD6F<96B^qq(14W8Xc*NuhmY3_Vq$LAa4?A5gH5ye=y;A1U~ z12Tbq9~i-Q(>nuepqscnaKkz2dVk|>R%4X|k z9>zGZU+LXK`*5}|wSNtb5o;kekEJg~9q|@`&+Z8IC)Uw*x$7u}cijrKAH%rcC!QfI zun(Fj*2(PdNkuIE2jG;;UmT9ULL4nPx^5N5xf=Xv&K{6|YskMd=niCks}NC{roEyhpY{YqiwhuyF}k$M%t|8&Zl4z3wKeId=M*n{-_-`{3t04*&3pcb|LigRY++ z{?{KK{?V>W^)**4(GUMDt*_C6yxZ}e4^pXj?|yzh?$&S{cgfIz=#I~5P14xR)^NL( zxO^@y);5OiV6#s5b2@I(E)fGFD?U!DmL*%laouhXgQZQuh&7)@WBSdwP1MUc1Gx_K z7wRpzbJQbd($?d28wY;P2z9ebci2Zv!r?ZbIe~)BX0*u)>5Hy#48qYS-Hz#SE8A#B zZ8XdcEz~!fNyz!mY=QQn!68R^!rTGsL9(H%NS!V`5o0LUe8$s=wFr(broIuVY;Kab z>Km*?xN#Hrz69O#O!TIh?U;gwgk>i-&Bu*r*w)LO$+~=Q1UW8FZb~i=f`Q~>m*vHr z(8ZV;+bYn`sTA#P$%L~y-NE1v?+oqIdd3*tTg^F|%|3^NH1tU}+YbFD$a^7=L3Tne zIg!oohP)H<50Ljl9)o-YlJ4H|w#hDmobzcmdp%_FN%%uzk2}S8Yb`5kKg)N<*qIJS zcOZv8&SvRjmQ{>8i|pwCK9-=rC4`|67QnL#*kzDZ=HRKrV*^`DK*gepar&c0k7y2?h08hsA4LqH&lkc@C=5{d}#pji}mIv|YR3 zZ@&4)Z{K=*oMX2S&BYk=A=hr7zv9sukDXDuZTj}pZPyB8K-&pCFOeNMpm-IJ7C$zs za@)x5BdYH&dO&;7zr*K`{nx=a4{)b4m@R~@4gPf3C*!N8B(8Roc)+(=7zbcW9EUyv zS4B?z9^^6hu`!kR7e6qnX4~lPUwUxljuGE2dPsZN|A8{QN>p1B;oWbpjxtz}B z4&FW^ul@L`Y>c31{BFYt-rh0Nt#HBi@%GWY{eGU`7_OIcIfY9hG+yaE%tduu! z8rUdqH%&P5js*S+ACMT=MZEtnaeLAKSzH%(pJmPmNyuF|6 zA`g+?-&zLvME`%6oqXMXQNB~-3tJX5cZR>hH^8}Ej^VPVs_GKG?AnI5sNJTYx2*j9 z@+FJTTi)jA=gsE`LRXxPKc;0igpEeawA&JvVMaqnL)cC-T9Q8APvIo^x5%L>hx#!eeN-*WB8u}8##CpBnnJiAdGY&m!d>nVs&U^j|`BFBE>;5jP6 z$bS+O=VvZHnH5@}8k@qzd6#QH73%N_*4Q*wRuC7bnjD28pW!6X+ACroWpgbVbI-@I ztY=bgi~C+FVZY7e$Hj;9L)*&7hH#ySbM1%E3uX9u`5ep3hvNC!SSE1sUU2gtzOGz+ z_&Qnix&4l2W#R=2J1QbhM;@h1(e`=y9~KEZQE)CmQvL!j;rI%UpWyaSaJ-J=kMI}f zA&%e3@f0l;ltVPJC>!xm{19IfI>*KQ=I?`O+>Kwt)}9Fisr(4_&*NFoby9fR~4}7l&{swSeiYuxm_#V}<&S}=<@)y{bNb5ng4FI1l6iH5ld!hW# z@xU(vK0)#q)n?$-?~=THzU&d_2FHHt;JOuYOtSY6KPQ_!;wL@g-{pbt^uT}Qfxqa1 zzwUwedf>-A@Nt;Ok^=L12Jk}ja-j#l!UMk^xGu<*WE1d0^LQuW{;Bx!frO=!_K3gB zi8J&*73VYk-YS&;k3Hi23V5OQ^NNT4WCtJmPFTuwJ?If9;}PdLw-@K97_tuoDU|;t z2Os(lT*3!j>S15*fnVu?Ujv-@&(CMQhkXlhT_i2ZyFBb4_rRYe+&}!gWsiqFTNg~& z=at9UoOU)R#0-OeVc2F90~`h%G$RpXqh+=jjZwm)z*?=?Mk5hxv#s(Vi$#rOxQQh! zGh`$;hV5W8OKu1nkysOp$KqDha9ZrvSa~oOP1^B9EMC5ZnXTb=D`7NQwh@mdY}RBX zo7?PAY-1Evw-J?Q1Wj7h+F(Y^Xwaezl6G5TBRURQ39Bibv=PQ`HG+{?)Jh`%P|RqG z#9(iP>{udcm~HJW7;BA3EZYj9=YkeSV>lW%%tXT6WLQxQ2uJNkBiNi1#I$2!*|HVOF_x1E ztufgm9*g9}PTGlRur)557{-Ri!rftUAZM2!WuU1Yz z2G%i=9W|q|WW=)a2pC)iPQ2!viKGRFgq?kxHyw?^sGT!RGRjHTz;fd|A=DN>Kc|h> zrP#B1s}gG|8pELxH0^LKXFhR6SkVnRacBp!jb_-6hjTh-<;hL0w%Gt_CtTSqYS9=@ ztEOmMc|%(`5?T}vv2v_8D-mZ7+H5A9S$Swv6cJo$C)}0|Rw9X%aufq?2`gff1Fyv+ zHbq2Y<+jz1zjUIYE#_>3a;ur2AF!Z{J&1cFA?M@;#_J`gltaU( z!=S&oUlLN>7Yiq{mCJG{AL9;G^#2U62q}J+h@o`(4.4→3 优先于 3.5→2;都不插→不动保持上次)。 +# 写后 cget 读回校验,失败记日志不重试风暴(状态翻身后才再评估)。 +# 触发即启动(trigger=boot);子进程崩则 on-fail 拉起,防常驻守护静默丢失。 +exec=/usr/data/mnt/sd_0/MeowOS/opt/bin/meow_route +args= +enabled=1 +restart=on-fail +backoff_ms=2000 +max_restart=5 +trigger=boot +cap=