/* test_bt_ctl.c — meow_netmgrd 蓝牙 P1 权威收口 纯逻辑宿主自测(本程序非生产代码)。 * * 通过 #include 生产源文件(meow_netmgrd.c,用 #define main 改名避免入口冲突),同一 TU 直接访问 * FILE-STATIC 函数/全局:bt_cmd_is_write / bt_write_authorize / bt_ctl_execute(connect/disconnect/ * pair/unpair/connected/a2dp/devices/status)。工具经桩脚本(g_bluetoothctl/g_hcitool/g_bluealsa_cli/ * g_bt_scan_cache 指向 $T/桩)覆盖,不依赖真实蓝牙栈。 * * 用法:cc -Wall -Wextra -I../meow_launcherd test_bt_ctl.c -o test_bt_ctl && ./test_bt_ctl */ #define main meow_netmgrd_prod_main_unused #include "meow_netmgrd.c" #undef main #include #include #include #include #include static int g_fail = 0; #define CHECK(cond) do { if (!(cond)) { printf(" FAIL: %s (line %d)\n", #cond, __LINE__); g_fail++; } \ else { printf(" ok : %s\n", #cond); } } while (0) static void wf(const char *p, const char *s) { FILE *f = fopen(p, "w"); if (f) { fputs(s, f); fclose(f); } } int main(void) { static const char *T = "/tmp/nmg_bt"; char p[192]; mkdir(T, 0755); /* 假 /sys/class/bluetooth/hci0(available/powered/address) */ { snprintf(p, sizeof p, "%s/bt", T); mkdir(p, 0755); snprintf(p, sizeof p, "%s/bt/hci0", T); mkdir(p, 0755); snprintf(p, sizeof p, "%s/bt/hci0/address", T); wf(p, "00:1A:7D:DA:71:13\n"); snprintf(p, sizeof p, "%s/bt/hci0/power", T); wf(p, "on\n"); } /* 桩:bluetoothctl(paired/devices/connect/remove)、hcitool con、bluealsa-cli a2dp、扫描缓存 */ snprintf(p, sizeof p, "%s/bluetoothctl", T); wf(p, "#!/bin/sh\ncase \"$1\" in\n" " paired|paired-devices|devices) echo 'Device 33:DE:2E:21:AD:30 Pudding'; echo 'Device 11:22:33:44:55:66 Speaker';;\n" " connect|disconnect|pair|remove) echo 'Controller 00:1A:7D:DA:71:13'; echo 'Device 33:DE:2E:21:AD:30 Connected: yes';;\n" "esac\nexit 0\n"); chmod(p, 0755); snprintf(p, sizeof p, "%s/hcitool", T); wf(p, "#!/bin/sh\necho '\t< ACL 33:DE:2E:21:AD:30 handle 12 state 1 lm MASTER'\n" "echo '\t< ACL 11:22:33:44:55:66 handle 13 state 1 lm SLAVE'\nexit 0\n"); chmod(p, 0755); snprintf(p, sizeof p, "%s/bluealsa-cli", T); wf(p, "#!/bin/sh\nif [ \"${1:-}\" = \"a2dp\" ]; then\n" "echo '/org/bluealsa/hci0/dev_33_DE_2E_21_AD_30/a2dpsrc:'\n" "echo '\tCodec: SBC'\necho '\tSampling: 44100 Hz'\necho '\tChannels: 2'\n" "echo '\tBits per Sample: 16'\necho '\tState: RUNNING'\necho '\tAcquired: yes'\nfi\nexit 0\n"); chmod(p, 0755); snprintf(p, sizeof p, "%s/bt_scan.txt", T); wf(p, "[NEW] Device 33:DE:2E:21:AD:30 Pudding\n[NEW] Device AA:BB:CC:DD:EE:FF Earbuds\n"); g_bluetoothctl = ""; { char x[160]; snprintf(x, sizeof x, "%s/bluetoothctl", T); static char s[160]; snprintf(s, sizeof s, "%s", x); g_bluetoothctl = s; } g_hcitool = ""; { char x[160]; snprintf(x, sizeof x, "%s/hcitool", T); static char s[160]; snprintf(s, sizeof s, "%s", x); g_hcitool = s; } g_bluealsa_cli = ""; { char x[160]; snprintf(x, sizeof x, "%s/bluealsa-cli", T); static char s[160]; snprintf(s, sizeof s, "%s", x); g_bluealsa_cli = s; } g_bt_scan_cache = ""; { char x[160]; snprintf(x, sizeof x, "%s/bt_scan.txt", T); static char s[160]; snprintf(s, sizeof s, "%s", x); g_bt_scan_cache = s; } g_bt_dir[0] = 0; snprintf(g_bt_dir, sizeof g_bt_dir, "%s/bt", T); ctl_result_t r; printf("== bt_cmd_is_write 分类(读/写级) ==\n"); CHECK(bt_cmd_is_write("status") == 0); CHECK(bt_cmd_is_write("paired") == 0); CHECK(bt_cmd_is_write("connected") == 0); CHECK(bt_cmd_is_write("a2dp") == 0); CHECK(bt_cmd_is_write("devices") == 0); CHECK(bt_cmd_is_write("on") == 1); CHECK(bt_cmd_is_write("off") == 1); CHECK(bt_cmd_is_write("connect") == 1); CHECK(bt_cmd_is_write("disconnect") == 1); CHECK(bt_cmd_is_write("pair") == 1); CHECK(bt_cmd_is_write("unpair") == 1); CHECK(bt_cmd_is_write("scan") == 1); printf("== bt_ctl_execute 写级(connect/disconnect/pair/unpair,经桩 bluetoothctl) ==\n"); bt_ctl_execute("connect", "33:DE:2E:21:AD:30", &r); CHECK(r.code == MEOW_OK); CHECK(strstr(r.text, "Connected") != NULL); bt_ctl_execute("disconnect", "33:DE:2E:21:AD:30", &r); CHECK(r.code == MEOW_OK); bt_ctl_execute("pair", "33:DE:2E:21:AD:30", &r); CHECK(r.code == MEOW_OK); bt_ctl_execute("unpair", "33:DE:2E:21:AD:30", &r); CHECK(r.code == MEOW_OK); CHECK(strstr(r.text, "Connected") != NULL); /* remove 桩回 Connected: yes */ bt_ctl_execute("connect", "", &r); CHECK(r.code == MEOW_ERR_INVAL); /* 缺 mac → INVAL */ bt_ctl_execute("scan", NULL, &r); CHECK(r.code == MEOW_OK); /* scan on(默认) */ CHECK(strstr(r.text, "scan on") != NULL); bt_ctl_execute("scan", "off", &r); CHECK(r.code == MEOW_OK); printf("== bt_ctl_execute 读级(connected/a2dp/devices/status,权威) ==\n"); bt_ctl_execute("connected", NULL, &r); CHECK(r.code == MEOW_OK); CHECK(strstr(r.text, "Device 33:DE:2E:21:AD:30") != NULL); CHECK(strstr(r.text, "Pudding") != NULL); bt_ctl_execute("a2dp", NULL, &r); CHECK(r.code == MEOW_OK); CHECK(strstr(r.text, "codec=SBC") != NULL); CHECK(strstr(r.text, "rate=44100") != NULL); CHECK(strstr(r.text, "acquired=1") != NULL); CHECK(strstr(r.text, "role=src") != NULL); snprintf(p, sizeof p, "%s/bt_scan.txt", T); wf(p, /* 重写(bt scan on 曾覆盖) */ "[NEW] Device 33:DE:2E:21:AD:30 Pudding\n[NEW] Device AA:BB:CC:DD:EE:FF Earbuds\n"); bt_ctl_execute("devices", NULL, &r); CHECK(r.code == MEOW_OK); CHECK(strstr(r.text, "Earbuds") != NULL); CHECK(strstr(r.text, "Device 33:DE:2E:21:AD:30") != NULL); bt_ctl_execute("status", NULL, &r); CHECK(r.code == MEOW_OK); CHECK(strstr(r.text, "connected=2") != NULL); printf("== bt_write_authorize(系统身份 + MeowOS 才放行写级) ==\n"); caller_t other; memset(&other, 0, sizeof other); other.kind = CALL_OTHER; caller_t sys; memset(&sys, 0, sizeof sys); sys.kind = CALL_SYS; snprintf(sys.pkg, sizeof sys.pkg, "meow_net"); CHECK(bt_write_authorize(&other, 1, "connect") == MEOW_ERR_PERM); /* 非系统 → 拒 */ CHECK(bt_write_authorize(&sys, 1, "connect") == MEOW_OK); /* 系统+meow → 放 */ CHECK(bt_write_authorize(&sys, 0, "connect") == MEOW_ERR_PERM); /* 系统+hiby → 拒 */ CHECK(bt_write_authorize(&other, 1, "status") == MEOW_OK); /* 读级任意 → 放 */ if (g_fail) { printf("\nBT_CTL TEST: %d FAIL\n", g_fail); return 1; } printf("\nBT_CTL TEST: ALL PASS\n"); return 0; }