From 9fbbd1aedad5c8b559be5c60f6a6deb258243a6b Mon Sep 17 00:00:00 2001 From: andy Date: Fri, 11 Sep 2026 13:07:37 +0100 Subject: [PATCH] Export BLE peripheral internals (GAP + BLE glue) to apps Add a data-driven firmware-symbol export mechanism (EXPORT_ENABLE list in build.sh, applied by the api_symbols.csv editor) and use it to enable all gap_* functions, the safe ble_glue_* status/lifecycle calls, and furi_hal_bt_init. Apps can now drive GAP directly, run a custom GATT server, set the advertised name / extra-beacon config, and read radio-stack status. The coprocessor FUS stack delete/install calls stay disabled to avoid erasing the radio firmware. 19 symbols newly exported; firmware links. --- README.md | 14 ++++++++++++++ build.sh | 24 ++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1e24af5..6c83dfd 100644 --- a/README.md +++ b/README.md @@ -165,6 +165,20 @@ Three facts about the Flipper Zero drive the design: `stm32wb5x_BLE_Stack_full_extended_fw.bin` (BLE 5 extended advertising, Coded PHY), which loads at 0x080C5000; it is not selected by this script. +### Extra firmware APIs exported to apps + +Beyond the ST BLE commands, `build.sh` enables a set of firmware functions that +stock firmware keeps internal, so any `.fap` on this firmware can use them. The +set is a list of name patterns in `build.sh` (`EXPORT_ENABLE`); each enabled +symbol costs one API-table entry. + +* **BLE peripheral internals** (`gap_*`, safe `ble_glue_*`, `furi_hal_bt_init`): + drive GAP directly, run a custom GATT server, change the advertised name and + the extra-beacon config, read connection state and radio-stack status, + without going through the firmware's serial profile. The coprocessor + firmware-update calls (`ble_glue_fus_stack_delete/install`) are deliberately + left disabled, since they can erase the radio stack. + `build.sh` also widens the GAP roles the firmware initialises (`GAP_PERIPHERAL_ROLE | GAP_CENTRAL_ROLE | GAP_OBSERVER_ROLE`) in `targets/f7/ble_glue/gap.c`. The app itself uses HCI-level scan and connect diff --git a/build.sh b/build.sh index 097b3b0..360e70d 100755 --- a/build.sh +++ b/build.sh @@ -101,13 +101,25 @@ API_CSV=targets/f7/api_symbols.csv # all also gap, hal, l2cap (~20 KB) # min only the functions BT Inspector imports (~1.5 KB) BLE_API="${BLE_API:-hci,gatt}" + +# --- Firmware API exported to .fap apps (in addition to the ST BLE commands) --- +# Each area is appended below; every enabled symbol stays in the firmware image. +# BLE peripheral internals: GAP control (advertised name, custom GATT server, +# extra-beacon config, connection state) and BLE-glue radio-stack status. +EXPORT_ENABLE="${EXPORT_ENABLE:-}" +EXPORT_ENABLE+=' +^gap_ +^ble_glue_(start|stop|get_c2_status|get_hardfault_info|force_c2_mode)$ +^furi_hal_bt_init$ +' +export EXPORT_ENABLE if grep -q "^Function,?," "$API_CSV" || ! grep -qE "^Header,\+,.*ble_hci_le\.h" "$API_CSV"; then # fbt notices the new headers, rewrites the csv with '?' entries and stops. echo ">> syncing API symbol table (expected to stop once)" ./fbt -j"${JOBS:-4}" "${FBT_ARGS[@]}" api_check || true fi python3 - "$API_CSV" "$BLE_API" "$APP_SRC" <<'PY' -import re, sys, glob +import os, re, sys, glob csv_path, mode, app_src = sys.argv[1:4] hdrs = {"hci": "ble_hci_le", "gap": "ble_gap_aci", "gatt": "ble_gatt_aci", "hal": "ble_hal_aci", "l2cap": "ble_l2cap_aci"} owner = {} @@ -124,17 +136,25 @@ elif mode == "min": else: want = set(mode.split(",")) selected = {fn for fn, key in owner.items() if key in want} -out, n_on = [], 0 +# Firmware symbols to force-enable, one regex per line, from $EXPORT_ENABLE. +enable_res = [re.compile(p) for p in os.environ.get("EXPORT_ENABLE", "").split() if p] +out, n_on, n_fw = [], 0, 0 for line in open(csv_path).read().splitlines(): parts = line.split(",") if len(parts) >= 3 and parts[0] == "Function" and parts[2] in owner: parts[1] = "+" if parts[2] in selected else "-" n_on += parts[1] == "+" + elif len(parts) >= 3 and parts[0] in ("Function", "Variable") and any(r.search(parts[2]) for r in enable_res): + if parts[1] != "+": + n_fw += 1 + parts[1] = "+" elif len(parts) >= 2 and parts[1] == "?": parts[1] = "-" if parts[0] == "Variable" else "+" out.append(",".join(parts)) open(csv_path, "w").write("\n".join(out) + "\n") print(f">> BLE API export ({mode}): {n_on} of {len(owner)} aci_*/hci_* functions enabled") +if enable_res: + print(f">> firmware API export: {n_fw} extra symbol(s) newly enabled") PY if [ "${1:-}" = "fap" ]; then