Files

137 lines
6.8 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
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;
}