fix(audiod): M50 蓝牙输出端到端 — 内联 DEV/CODEC 打开 + 失败必回落 DAC + MAC 解析修正
① ALSA 正确用法(核心):不再写 /usr/data/alsa.conf(HiBy 播放器数据文件、语法非法、
libasound 从不加载,改它对解析零影响)。改为 snd_pcm_open("bluealsa:DEV=<mac>,
PROFILE=a2dp,CODEC=<token>"),参数名严格取 /etc/alsa/conf.d/20-bluealsa.conf 的
pcm.bluealsa @args[DEV PROFILE CODEC VOL SOFTVOL DELAY SRV](实测未知参数会被
alsa-lib 拒绝);删掉 bt_apply_device_conf/bt_apply_codec_conf 两条改写分支。
② 硬 bug:bt_dev_detect_mac() 旧逻辑取端点 token「最后一个 '/' 之后」——真机
bluealsa-cli list-pcms 输出是 D-Bus 路径 /org/bluealsa/hci0/dev_33_DE_2E_21_AD_30/
a2dpsrc/source,旧代码会把 "source" 当 MAC(旧单测喂的是人造输入所以一直是绿的)。
改按 dev_XX_XX_XX_XX_XX_XX 段解析,兼容老式 a2dpsrc/<MAC>。
③ codec:settings bt.codec 经 bt_dev_codec_token() 归一成 bluealsa canonical 名
(v4.1.1 a2dp-codecs.c 别名表,strcasecmp);auto/未知 → unchanged(不干预协商)。
④ 失败必回落(硬验收):新增 BT_ST_IDLE/OK/FAIL 状态机 —— 无端点/未连接/set_params
失败/写路径致命错(ENODEV 等)都回落 DAC 继续出声,绝不整机静音;回落前同步武装
numid=9(hbc3000 未烧+enable 开 PCM 会楔死整机);STATE 增 bt=/btdev=/btcodec=
三键供面板显示「输出=蓝牙(失败)」,volctl 回落时报 dac。
⑤ 防重试风暴:只在开流/重配边界重试,指数退避 2s→60s(bt_dev_should_try),写循环内
绝不重试;用户显式切目标才清退避。
⑥ 音量:BT 真走 A2DP 时仍不下发 DAC 反转(回归确认),回落 DAC 时按 DAC 音量控;
AVRCP 一键置最大从 100 改 127(bluealsa-cli volume 满量程 [0,127],旧值只到 79%)。
⑦ build_audiod.sh:ROOT/REPO 自动推导,ZIG/CC/LIBBT/ASOUND_SRC 可环境变量覆盖(旧
hiby_os_crack 路径在多数 checkout 里不存在),宿主链接 -l:libasound.so.2 失败退
-lasound;保留 M43 的 meow_audio time32 cli 目标。
宿主:test_bt_dev 51/51(真机 D-Bus 路径格式/别名表/退避),test_audiod_host 109/0,
0 warning。真机:新二进制 glibc-dynamic 上机正常,DAC 出声回归通过,无端点回落 DAC
出声(played/rms 实证),/usr/data/alsa.conf 全流程零写入;耳机出声一项待耳机上电。
不提交二进制、不改 fw_content.conf 钉值(按塔交付形态政策,由 M51 统一重编)。
This commit is contained in:
1 parent
ca042aa79c
commit
33bef36d16
6 files changed
+605
-339
No files matched your search
@@ -1,12 +1,19 @@
|
||||
/* bt_dev.h — 蓝牙 A2DP 设备自识别(DEV 自动更新纯逻辑,宿主可单测)。
|
||||
/* bt_dev.h — 蓝牙 A2DP 端点选择 + PCM 名构造 + 回落退避(纯逻辑,宿主可单测)。
|
||||
*
|
||||
* 背景:/usr/data/alsa.conf 的 `pcm.bluealsa`(plug→bluealsa)需把 DEV/device 钉在当前
|
||||
* 连接的 A2DP sink 设备 MAC 上才能正确出声。本模块提供两段纯逻辑(无 meow_* / popen / 文件
|
||||
* I/O —— meow_audiod 负责读文件与执行系统命令):
|
||||
* - bt_dev_detect_mac:从 `bluealsa-cli list-pcms` 输出提取第一个 a2dpsrc 端点的设备 MAC;
|
||||
* - bt_dev_rewrite:幂等改写 alsa.conf 文本,把 `pcm.bluealsa` 块内 `DEV=<mac>` 与
|
||||
* `device <mac>` 两处换成目标 MAC(保留引号风格 / codec / 其余 token)。
|
||||
* 纯 libc(string / stdlib),独立编译,宿主零链接重。
|
||||
* 背景(M50 真机定案):`/usr/data/alsa.conf` **不是** alsa 配置(是 HiBy 播放器的数据文件,
|
||||
* libasound 从不加载),改它对实际解析零影响。真正生效的是 alsa-lib 自带的
|
||||
* `/etc/alsa/conf.d/20-bluealsa.conf`:
|
||||
*
|
||||
* pcm.bluealsa {
|
||||
* @args [ DEV PROFILE CODEC VOL SOFTVOL DELAY SRV ] ← 只有这 7 个名字
|
||||
* ... type plug / slave.pcm { type bluealsa ... }
|
||||
* }
|
||||
*
|
||||
* 其 `@args` 均可从 PCM 名内联传入(`snd_pcm_open("bluealsa:DEV=<mac>,PROFILE=a2dp,
|
||||
* CODEC=<token>")`),未声明的参数会被 alsa-lib 拒绝(parse_args: Unknown parameter)——
|
||||
* 所以本模块只生成这 7 个里的 3 个,且**不改任何文件**。
|
||||
*
|
||||
* 纯 libc(string/stdlib),无 meow_* / popen / 文件 I/O —— meow_audiod 负责探测与打开。
|
||||
*/
|
||||
#ifndef BT_DEV_H
|
||||
#define BT_DEV_H
|
||||
@@ -14,14 +21,35 @@
|
||||
#include <stddef.h>
|
||||
|
||||
/* 解析 bluealsa-cli list-pcms 输出,取第一个 a2dpsrc/a2dp_source 端点的设备 MAC。
|
||||
* 返回 0=找到并写入 mac(NUL 结尾),-1=无 a2dpsrc 端点 / 参数非法。macsz 建议 ≥18。 */
|
||||
* 真实行为 D-Bus 对象路径(bluealsa 4.1.1):
|
||||
* /org/bluealsa/hci0/dev_33_DE_2E_21_AD_30/a2dpsrc/source
|
||||
* 返回 0=找到并写入 mac(17 字符、大写冒号分隔,NUL 结尾),-1=无 a2dpsrc 端点 / 参数非法。
|
||||
* macsz ≥ 18。 */
|
||||
int bt_dev_detect_mac(const char *listpcms, char *mac, size_t macsz);
|
||||
|
||||
/* 幂等改写 alsa.conf 文本(in_len 不含 NUL):把 `pcm.bluealsa` 块内 `DEV=<mac>` 与
|
||||
* `device <mac>` 两处 MAC 换成 mac(保留引号风格、codec/其它 token 原样)。
|
||||
* 返回 0=已改动(*out 与 *out_len 给出新文本,调用方负责 free);1=无需改动(两端已一致);
|
||||
* -1=无 pcm.bluealsa / 无 DEV= 或 device token / 参数非法(不动)。 */
|
||||
int bt_dev_rewrite(const char *in, size_t in_len, const char *mac,
|
||||
char **out, size_t *out_len);
|
||||
/* 统计 list-pcms 输出里的 a2dpsrc/a2dp_source 端点数(0=无可用 A2DP 源端点)。
|
||||
* 用于「先探测端点、再决定是否打开」——无端点时省掉一次注定失败的 open。 */
|
||||
int bt_dev_count_src(const char *listpcms);
|
||||
|
||||
/* settings.conf `bt.codec` → bluealsa CODEC 参数 token。
|
||||
* bluealsa 4.1.1 的 a2dp_codecs_codec_id_from_string() 用 strcasecmp 匹配 canonical 名与别名,
|
||||
* 故大小写不敏感;本函数把它归一成 canonical 名(日志/STATE 用),未知值/auto/unchanged →
|
||||
* "unchanged"(不改协商结果,等价 20-bluealsa.conf 的 defaults.bluealsa.codec)。
|
||||
* 返回 out(调用方给的 buf)。outsz 建议 ≥16。 */
|
||||
const char *bt_dev_codec_token(const char *setting, char *out, size_t outsz);
|
||||
|
||||
/* 组 snd_pcm_open 的 PCM 名:
|
||||
* bluealsa:DEV=<mac>,PROFILE=a2dp,CODEC=<token>
|
||||
* mac 非 6 组十六进制 → -1(不拼非法名字);token 为空 → 用 "unchanged"。
|
||||
* 返回 0=写好(out NUL 结尾)。outsz 建议 ≥96。 */
|
||||
int bt_dev_pcm_name(const char *mac, const char *codec_token, char *out, size_t outsz);
|
||||
|
||||
/* 回落退避:连续失败 fails 次后的重试间隔 ms(2s→4s→8s→16s→32s→60s 封顶;fails=0 → 0)。
|
||||
* 防重试风暴(M10 教训):失败越多等越久,绝不每次 OPEN 都硬打一次 BT。 */
|
||||
unsigned bt_dev_backoff_ms(unsigned fails);
|
||||
|
||||
/* 纯决策:此刻是否允许再尝试一次 BT。fails=0 → 允许;否则要求距上次失败 ≥ 退避间隔。
|
||||
* since_ms<0(时钟异常)按「允许」处理,避免永久卡死。 */
|
||||
int bt_dev_should_try(unsigned fails, long long since_ms);
|
||||
|
||||
#endif /* BT_DEV_H */
|
||||
Reference in new issue
Block a user