fix(keys): 插孔消抖 + 音量 ramp 3s 上限 + 亮度写日志 — 耳机插拔 ADC 幽灵音量键修复

真机实证(meow_20260901_034946.log): 4.4 插入瞬间电气瞬态在 jz_adc_aux(event2)
产生 VOL_UP 幽灵按住, vol_ramp 24%→上限50 (225391 ramp 起→227213 爬满,
紧随 audiod jack changed). 修(限 meow_launcherd/+meow_watchdog/):
① launcher audio.c + watchdog 各自读 /sys/class/switch/{headset,balance}/state
  (节流缓存 1s/500ms, 热路径不每圈读文件), 变化后 800ms 内忽略音量键边沿
  (vol_ramp_begin 不起/在爬 ramp 中止/wd_vol_adj 单步忽略)
② ramp 总时长上限 VOL_RAMP_MAX_MS=3000 兜底防一次幽灵打满(正常长按 24→50 ~1.4s 不伤)
③ write_brightness(val,src) 全 10 调用点带源+逐写 logmsg, 亮度跳上限下次可定位
  (grep 全库: 写 backlight 仅 launcher/watchdog/svc_power/bootmenu, 无确定 255 路径)
宿主: 新 test_vol_ramp_jack 15/15 PASS(单击/长按回归+3s cap+消抖忽略/中止/恢复);
test_wd_fw 17/17 + test_settings_brightness + test_notif_tf PASS; MIPS -Wall -Wextra 0 warning
(顺带修 watchdog 既有 sys/poll.h→poll.h 重定向 warning).
watchdog 已热更设备 /usr/data(baa997ea); launcher 7be1d4eb 待固件. fw_content.conf 已更新.
遗留: SDK meow_ui_input.c 音量键路径需同款消抖(sdk/ 有主未动)
This commit is contained in:
MeowOS committed 2026-09-01 04:28:10 +08:00
1 parent 44d170413d
commit 4bafdb5d69
13 files changed
+348 -20

No files matched your search

+73
View File
@@ -153,8 +153,65 @@ static unsigned long long vol_ramp_next_at = 0;
static unsigned long long vol_ramp_press_at = 0; /* M2.18 Bug 4:本方向键按下时刻(长按判据) */
/* ---- 插孔消抖(2026-09-01,真机日志实证)----
* 4.4/3.5 耳机插拔的电气瞬态在音量键 ADC(jz_adc_aux,event2)上产生 VOL_UP 幽灵按住
* (EVIOCGKEY 轮询到持续 down),vol_ramp 一路爬到上限:日志 225391「volume UP <- ramp」
* → 227213「ramp end -> 50」,紧接着 audiod 才报「route: jack changed -> 4.4 balance」。
* 修法:/sys/class/switch/{headset,balance}/state 任一变化后 JACK_DEBOUNCE_MS 内忽略音量键
* 边沿(vol_ramp_begin 不起、vol_ramp_tick 在爬也中止)。插拔耳机时没人按音量,误伤可忽略。
* 检测走 1s 节流读缓存——绝不在 10ms 主循环热路径上每圈读文件。 */
/* 宿主测试可 -D 覆盖(同 meow_settings.c MEOW_SETTINGS_FILE 惯例) */
#ifndef JACK_HS_STATE
#define JACK_HS_STATE "/sys/class/switch/headset/state"
#endif
#ifndef JACK_BAL_STATE
#define JACK_BAL_STATE "/sys/class/switch/balance/state"
#endif
static int jack_combo_cached = -1; /* hs*2+bal;-1=未初始化/节点缺失 */
static unsigned long long jack_poll_at = 0; /* 上次节流读时刻 */
static unsigned long long jack_changed_at = 0; /* 最近一次检测到插孔变化的时刻(0=无) */
/* 读两个插孔开关节点合成 hs*2+bal;两节点都不可读返回 -1(不更新缓存,不误判变化)。 */
static int jack_combo_read(void)
{
int hs = read_file_int(JACK_HS_STATE);
int bal = read_file_int(JACK_BAL_STATE);
if (hs < 0 && bal < 0) return -1;
return (hs > 0 ? 2 : 0) | (bal > 0 ? 1 : 0);
}
/* 返回 1=插孔变化后消抖窗口内(音量键边沿应忽略/在爬 ramp 应中止)。
* 自节流:每 JACK_POLL_MS 才真正读一次 sysfs。 */
static int jack_debounce_active(void)
{
unsigned long long now = now_ms();
if (now - jack_poll_at >= JACK_POLL_MS) {
jack_poll_at = now;
int c = jack_combo_read();
if (c >= 0) {
if (jack_combo_cached >= 0 && c != jack_combo_cached) {
jack_changed_at = now;
logmsg("jack state changed (%d -> %d), vol-key debounce %dms",
jack_combo_cached, c, JACK_DEBOUNCE_MS);
}
jack_combo_cached = c;
}
}
return jack_changed_at && (now - jack_changed_at < (unsigned long long)JACK_DEBOUNCE_MS);
}
static void vol_ramp_begin(int delta)
{
if (jack_debounce_active()) { /* 插孔瞬态期:忽略音量键边沿(幽灵按下) */
logmsg("volume adj %+d ignored (jack debounce)", delta);
return;
}
int target = vol_clamp(settings_volume + delta);
if (target == settings_volume) return;
vol_ramp_dir = (target > settings_volume) ? 1 : -1;
@@ -175,6 +232,22 @@ int vol_ramp_tick(int key_held)
unsigned long long now = now_ms();
if (now < vol_ramp_next_at) return 1;
vol_ramp_next_at = now + VOL_RAMP_MS;
/* 插孔消抖:插拔瞬态的幽灵按住正在驱动 ramp(真机实证 24%→上限 50)——
* 一旦检测到插孔变化(1s 节流轮询),立即中止在爬的 ramp。 */
if (jack_debounce_active()) {
vol_ramp_dir = 0; vol_ramp_target = -1;
meow_settings_save();
logmsg("volume ramp aborted (jack debounce) -> %d", settings_volume);
return 0;
}
/* 兜底:ramp 总时长上限 VOL_RAMP_MAX_MS——防任何「持续按住」假象(ADC 噪声卡 key_held=1)
* 一次打满/打到底。正常长按 0→上限(通常 ≤2.7s)不受影响;到顶想再调需松手重按。 */
if (now - vol_ramp_press_at >= (unsigned long long)VOL_RAMP_MAX_MS) {
vol_ramp_dir = 0; vol_ramp_target = -1;
meow_settings_save();
logmsg("volume ramp force-stop (%dms cap) -> %d", VOL_RAMP_MAX_MS, settings_volume);
return 0;
}
/* 先看是否已到「当前目标值」(settings_volume 等于 target,而非候选 v)——
* 因为一旦在 target 再取 v=settings_volume+dir 便越过 target,导致 hold_wait 失效继续爬。 */
if (settings_volume == vol_ramp_target) {