feat(bt): 蓝牙P2 source实装 — audiod OUT_BT输出目标(libasound直连pcm.bluealsa,BT独立目标不动DAC独占/FPGA/音量反转)+音量AVRCP隔离(不下发DAC反转)+codec生效+MSG_AUDIO_OUTPUT/CLI;宿主67pass/0warning;sink标记P2.5;遗留mipsel静态dlopen不支持libasound(硬集成项)

This commit is contained in:
AskaEth committed 2026-09-03 20:52:06 +08:00
1 parent 1f6d390e1c
commit 71b2dafecc
5 files changed
+587 -42

No files matched your search

+88
View File
@@ -153,6 +153,22 @@ static int start_audiod(void)
return start_audiod_ex("file", NULL, NULL);
}
/* 带自定义 settings.conf 的启动(P2 蓝牙:测 audio.output_bt / bt.codec 读取生效) */
static int start_audiod_settings(const char *sink, const char *settings_path)
{
pid_t pid = fork();
if (pid == 0) {
setenv("MEOW_AUDIO_SINK", sink, 1);
setenv("MEOW_AUDIO_OUT", TWAV, 1);
setenv("MEOW_AUDIO_SOCK", TSOCK, 1);
setenv("MEOW_AUDIO_FORCE", "1", 1);
if (settings_path) setenv("MEOW_AUDIO_SETTINGS", settings_path, 1);
execl("./meow_audiod_host", "meow_audiod_host", (char *)0);
_exit(127);
}
return pid;
}
/* 直接客户端 open */
static int do_open(struct cli *c, int rate, int ch, int fmt, m_audio_open_ack_t *ack)
{
@@ -690,6 +706,78 @@ int main(void)
check(eok, "fresh OPEN after overflow (table recycled, no exhaustion/wedge)");
check(stop_audiod_tmo(5000) != 0, "audiod not wedged by overflow (SIGTERM clean exit)");
/* ---- T11:P2 蓝牙 输出目标(OUT_BT)+ 音量 AVRCP 隔离 + 格式归一 + codec。
* 宿主以 FILE sink 跑(真 bluealsa 传输留给真机),验证目标选择/音量隔离/格式逻辑:
* - settings.conf `audio.output_bt=1` + `bt.codec=SBC` → target=bt / codec=SBC / volctl=avrcp / grant fmt=S16;
* - BT 下 MSG_AUDIO_VOLUME 设置:**不下发 DAC 音量反转**——g_vol_pct 不变、不持久化 audio.volume、
* volctl 仍 avrcp(隔离成立);
* - MSG_AUDIO_OUTPUT 切回 DAC:target=dac / volctl=dac;此后音量设置写 DAC + 持久化 audio.volume。
* 断言:BT 路径绝不动 DAC 音量(plan §三/§五「两套隔离」);BT 格式归一=S16;codec 读到生效。 ---- */
printf("[T11 BT output target + AVRCP vol isolation]\n");
unlink(TSOCK); unlink(TWAV);
const char *tconf = "/tmp/meow_test_settings.conf";
FILE *tf = fopen(tconf, "w");
if (tf) { fprintf(tf, "# meow-settings 1\naudio.volume = 60\naudio.output_bt = 1\nbt.codec = SBC\n"); fclose(tf); }
g_audiod_pid = start_audiod_settings("file", tconf);
usleep(400000);
struct cli b11;
check(cli_connect(&b11) == 0, "connect B11");
m_audio_open_ack_t ack11;
check(do_open(&b11, 44100, 2, AUDIO_FMT_S16, &ack11) == 0 && ack11.err == MEOW_OK, "open B11 (bt)");
char q11[1024];
check(do_query(&b11, q11, sizeof q11) == 0 && strstr(q11, "target=bt"),
"settings output_bt=1 -> target=bt");
check(strstr(q11, "codec=SBC") != NULL, "settings bt.codec=SBC -> codec=SBC");
check(strstr(q11, "volctl=avrcp") != NULL, "bt -> volctl=avrcp (AVRCP vol control)");
check(strstr(q11, "fmt=S16") != NULL, "bt grant fmt=S16 (format normalize)");
/* BT/file sink 写一段流(应正常落盘到 WAV) */
do_write(&b11, pcm, (uint32_t)gen_sine(pcm, sizeof pcm, (int)(ack11.grant_fmt ? ack11.grant_fmt : AUDIO_FMT_S16), 600, 440, 44100));
usleep(150000);
/* 音量设置 while BT:不下发 DAC——g_vol_pct 不变(60)、不持久化 audio.volume=40、volctl 仍 avrcp */
{
int32_t pct = 40;
if (sf(b11.fd, MSG_AUDIO_VOLUME, 8, &pct, sizeof pct) == 0) {
uint8_t ab[64]; uint16_t at; rf(b11.fd, &at, ab, sizeof ab); /* 消费 ACK */
}
usleep(100000);
}
check(do_query(&b11, q11, sizeof q11) == 0 && strstr(q11, "volctl=avrcp"),
"vol set while bt -> volctl still avrcp (isolation)");
check(strstr(q11, "vol=60") != NULL, "vol set while bt -> DAC vol unchanged (60)");
{
FILE *chk = fopen(tconf, "r"); int has40 = 0; char l[128];
if (chk) { while (fgets(l, sizeof l, chk)) if (strstr(l, "audio.volume = 40")) has40 = 1; fclose(chk); }
check(!has40, "bt vol set does NOT persist audio.volume=40");
}
/* MSG_AUDIO_OUTPUT 切回 DAC */
{
m_audio_output_t oo; oo.target = AUDIO_OUT_DAC;
if (sf(b11.fd, MSG_AUDIO_OUTPUT, 9, &oo, sizeof oo) == 0) {
uint8_t ab[64]; uint16_t at; rf(b11.fd, &at, ab, sizeof ab);
}
usleep(150000);
}
check(do_query(&b11, q11, sizeof q11) == 0 && strstr(q11, "target=dac"),
"MSG_AUDIO_OUTPUT -> target=dac");
check(strstr(q11, "volctl=dac") != NULL, "dac -> volctl=dac");
/* 现在音量设置应写 DAC + 持久化 */
{
int32_t pct = 40;
if (sf(b11.fd, MSG_AUDIO_VOLUME, 10, &pct, sizeof pct) == 0) {
uint8_t ab[64]; uint16_t at; rf(b11.fd, &at, ab, sizeof ab);
}
usleep(150000);
}
check(do_query(&b11, q11, sizeof q11) == 0 && strstr(q11, "vol=40"), "dac vol set -> g_vol_pct=40");
{
FILE *chk = fopen(tconf, "r"); int has40 = 0; char l[128];
if (chk) { while (fgets(l, sizeof l, chk)) if (strstr(l, "audio.volume = 40")) has40 = 1; fclose(chk); }
check(has40, "dac vol set persists audio.volume=40");
}
do_ctrl(&b11, MSG_AUDIO_STOP, ack11.stream_id);
close(b11.fd);
stop_audiod();
printf("=== SUMMARY: pass=%d fail=%d ===\n", g_pass, g_fail);
return g_fail ? 1 : 0;
}