From e71c3894a2655b32e44e7701c1358d22ccf82f73 Mon Sep 17 00:00:00 2001 From: liquidraver <504870+liquidraver@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:02:12 +0200 Subject: [PATCH] enable bluetooth privacy on esp32 to counter ios/esp bug android on official app needs a manual BT bond --- zephcore/adapters/ble/ZephyrBLE.cpp | 5 +- zephcore/boards/common/esp32_common.conf | 4 + zephcore/boards/common/zephcore_common.conf | 414 ++++++++++---------- 3 files changed, 213 insertions(+), 210 deletions(-) diff --git a/zephcore/adapters/ble/ZephyrBLE.cpp b/zephcore/adapters/ble/ZephyrBLE.cpp index 8805094..eb9cfb8 100644 --- a/zephcore/adapters/ble/ZephyrBLE.cpp +++ b/zephcore/adapters/ble/ZephyrBLE.cpp @@ -6,9 +6,8 @@ * Pairing is triggered reactively by ATT_ERR_AUTHENTICATION on secured GATT * attributes (Apple §55 compliant — no proactive Security Request on connect). * - * Advertising: Public identity address (CONFIG_BT_PRIVACY disabled). - * Android's Flutter BLE plugin fails to connectGatt() to RPA-advertised devices - * from app context. Arduino MeshCore also uses public addresses. + * Advertising: ESP32 enables CONFIG_BT_PRIVACY in esp32_common.conf; nRF uses public identity. + * Android Flutter may fail connect-from-app to RPA unless bonded; Arduino MeshCore uses public. */ #include diff --git a/zephcore/boards/common/esp32_common.conf b/zephcore/boards/common/esp32_common.conf index c015335..c564985 100644 --- a/zephcore/boards/common/esp32_common.conf +++ b/zephcore/boards/common/esp32_common.conf @@ -8,6 +8,10 @@ # DLE managed internally by Espressif blob — no CONFIG_BT_CTLR_DATA_LENGTH_MAX # TX power managed internally by Espressif blob — no CONFIG_BT_CTLR_TX_PWR_* +# Host privacy: required for reliable iOS SMP on Espressif controller (Zephyr #84182-class). +# Android MeshCore may need in-app bond or system pairing when using RPA. +CONFIG_BT_PRIVACY=y + # BLE thread stacks — ESP32 software BLE controller needs larger stacks CONFIG_BT_TX_PROCESSOR_STACK_SIZE=2048 diff --git a/zephcore/boards/common/zephcore_common.conf b/zephcore/boards/common/zephcore_common.conf index d7e6965..5cc3f4e 100644 --- a/zephcore/boards/common/zephcore_common.conf +++ b/zephcore/boards/common/zephcore_common.conf @@ -1,207 +1,207 @@ -# ZephCore Common Configuration -# Included by ALL boards regardless of MCU (nRF52, nRF54L, ESP32, MG24, etc.) -# Contains application-level settings and platform-agnostic BLE/storage/radio config. -# -# Platform-specific configs (nrf52_common.conf, esp32_common.conf, etc.) only -# contain overrides and additions unique to that platform. - -# ========== Core Settings ========== -CONFIG_MAIN_STACK_SIZE=8192 -CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=8192 -CONFIG_EVENTS=y - -CONFIG_CPP=y -CONFIG_STD_CPP17=y - -# ========== Printf Formatting ========== -# Enable floating point support in printf/sprintf (required for CLI) -CONFIG_CBPRINTF_FP_SUPPORT=y - -# ========== Crypto (PSA) ========== -# Required for mesh encryption (AES-ECB, SHA256, HMAC) -CONFIG_MBEDTLS=y -CONFIG_MBEDTLS_PSA_CRYPTO_C=y -CONFIG_PSA_WANT_ALG_SHA_256=y -CONFIG_PSA_WANT_ALG_ECB_NO_PADDING=y -CONFIG_PSA_WANT_KEY_TYPE_AES=y -CONFIG_PSA_WANT_ALG_HMAC=y -CONFIG_PSA_WANT_KEY_TYPE_HMAC=y - -# ========== Stack Protection ========== -CONFIG_HW_STACK_PROTECTION=y -CONFIG_THREAD_NAME=y - -# ========== Hardware Basics ========== -CONFIG_ADC=y -CONFIG_HWINFO=y -CONFIG_REBOOT=y - -# ========== LoRa ========== -CONFIG_LORA=y -CONFIG_LORA_MODULE_BACKEND_NATIVE=y -CONFIG_REGULATOR=y - -# ========== Display Subsystem ========== -# Display and CFB are auto-enabled by ZEPHCORE_UI_DISPLAY (Kconfig select) -# when "zephyr,display" chosen node exists in the board's devicetree. -# No need to set CONFIG_DISPLAY or CONFIG_CHARACTER_FRAMEBUFFER here. - -# Heap baseline — display boards override for larger framebuffers. -CONFIG_HEAP_MEM_POOL_SIZE=2048 - -# ========== Sensor Subsystem ========== -# Sensors are auto-detected at runtime via I2C scan -CONFIG_SENSOR=y -CONFIG_I2C=y - -# ========== GNSS Subsystem ========== -# Driver auto-selected from board DTS compatible (zero overhead if no GNSS in DT): -# quectel,lc76g -> Quectel LCx6G driver -# luatos,air530z -> LuatOS Air530Z driver -# gnss-nmea-generic -> passive NMEA parser -CONFIG_GNSS=y -CONFIG_MODEM_MODULES=y - -# ========== BLE Stack (common to ALL platforms) ========== -CONFIG_BT=y -CONFIG_BT_PERIPHERAL=y -CONFIG_BT_ZEPHYR_NUS=y -CONFIG_BT_ZEPHYR_NUS_DEFAULT_INSTANCE=n -CONFIG_BT_DEVICE_NAME="MeshCore" -CONFIG_BT_DEVICE_NAME_DYNAMIC=y -CONFIG_BT_DEVICE_NAME_MAX=29 -CONFIG_BT_DEVICE_NAME_GATT_WRITABLE=y -CONFIG_BT_DEVICE_APPEARANCE=0 -CONFIG_BT_MAX_CONN=1 - -# SMP: MITM passkey, bonding, enforce bonding -CONFIG_BT_SMP=y -CONFIG_BT_SMP_ENFORCE_MITM=y -CONFIG_BT_APP_PASSKEY=y -CONFIG_BT_BONDABLE=y -CONFIG_BT_BONDING_REQUIRED=y -CONFIG_BT_MAX_PAIRED=5 -CONFIG_BT_KEYS_OVERWRITE_OLDEST=y - -# Connection parameter update — disabled because we apply conn params -# manually after initial sync completes (zephcore_ble_conn_params_ready). -# The auto-update would fire too early and disrupt channel/contact sync. -CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=n - -# MTU max (controller limit 251, L2CAP MTU 247, ATT payload 244) -CONFIG_BT_BUF_ACL_RX_SIZE=251 -CONFIG_BT_BUF_ACL_TX_SIZE=251 -CONFIG_BT_L2CAP_TX_MTU=247 - -# BLE TX buffers — default 3 is too low, causes system workqueue deadlock -# when BLE activity bursts (DLE + param update + ATT) exhaust all buffers -# and bt_hci_cmd_alloc(K_FOREVER) blocks the cooperative syswq forever. -CONFIG_BT_BUF_ACL_TX_COUNT=7 -CONFIG_BT_L2CAP_TX_BUF_COUNT=7 -CONFIG_BT_CONN_TX_MAX=7 - -# BLE RX thread stack — default 1200 too small for ATT handlers + logging + asserts -CONFIG_BT_RX_STACK_SIZE=2048 - -# Data Length Extension update support (host side) -CONFIG_BT_USER_DATA_LEN_UPDATE=y - -# PHY update callback — lets us log the negotiated PHY and sequence DLE -# after the PHY procedure completes (avoids LL procedure collision). -# -# NOTE: BT_USER_PHY_UPDATE disables BT_AUTO_PHY_UPDATE (Kconfig default). -# We intentionally do NOT set BT_AUTO_PHY_UPDATE — peripheral-initiated -# PHY updates cause iOS disconnects. The phone (central) initiates PHY -# update and le_phy_updated fires regardless. Coded PHY can be requested -# manually after security is established (future enhancement). -CONFIG_BT_USER_PHY_UPDATE=y - -# Privacy disabled — Android's Flutter BLE plugin fails to connect to -# RPA-advertised devices from app context (system BT settings works fine). -# Arduino MeshCore doesn't use RPA either. Actual link security comes from -# SMP pairing (passkey + SC + MITM + bonding), not address privacy. -# CONFIG_BT_PRIVACY=y -# NOTE: SC_PAIR_ONLY intentionally NOT set — Windows can't handle SC passkey -# pairing (never prompts for PIN). Allowing both Legacy and SC lets Windows -# pair with Legacy while iOS/Android use SC. - -# Disable Extended Advertising (ALL boards) -# Some controllers (MG24, ESP32) auto-select ext adv PDUs. -# Web Bluetooth (Chrome) can't discover devices using ext adv PDUs. -# Legacy ADV_IND works universally with all BLE scanners and web apps. -CONFIG_BT_EXT_ADV=n - -# Device Information Service (Apple requirement) -CONFIG_BT_DIS=y -CONFIG_BT_DIS_MANUF_NAME=y -CONFIG_BT_DIS_MANUF_NAME_STR="ZephCore" -CONFIG_BT_DIS_MODEL_NUMBER=y -CONFIG_BT_DIS_MODEL_NUMBER_STR="ZephCore" -CONFIG_BT_DIS_FW_REV=y -CONFIG_BT_DIS_FW_REV_STR="1.13.0" -CONFIG_BT_DIS_SW_REV=y -CONFIG_BT_DIS_SW_REV_STR="Zephyr" -CONFIG_BT_DIS_PNP=n - -# Disable GATT Caching (Robust Caching / Database Hash) -# With caching enabled (Kconfig default), Zephyr silently drops ATT requests -# from "change-unaware" clients after the GATT database changes. This breaks -# service discovery on phones that enable Robust Caching (modern iOS/Android). -# Arduino SoftDevice has no GATT caching — disabling matches that behavior. -CONFIG_BT_GATT_CACHING=n - -# Persistent bonds (NVS) -CONFIG_BT_SETTINGS=y -CONFIG_SETTINGS_RUNTIME=y - -# ========== Flash & Storage (common to ALL platforms) ========== -CONFIG_FLASH=y -CONFIG_FLASH_MAP=y -CONFIG_FLASH_PAGE_LAYOUT=y -CONFIG_SETTINGS=y - -# BLE bonds via file-based settings on LittleFS (all platforms) -CONFIG_NVS=n -CONFIG_SETTINGS_NVS=n -CONFIG_SETTINGS_FILE=y -CONFIG_SETTINGS_FILE_PATH="/lfs/settings" - -# LittleFS for DataStore -CONFIG_FILE_SYSTEM=y -CONFIG_FILE_SYSTEM_LITTLEFS=y -CONFIG_FS_LITTLEFS_NUM_FILES=8 -CONFIG_FS_LITTLEFS_NUM_DIRS=4 -CONFIG_FS_LITTLEFS_CACHE_SIZE=256 -CONFIG_FILE_SYSTEM_MKFS=y - -# ========== Input Subsystem ========== -CONFIG_INPUT=y -CONFIG_INPUT_EVENT_DUMP=n -# Synchronous mode: callbacks run in reporting context (GPIO ISR / syswq) -# instead of a dedicated 1KB input thread. Saves a thread stack. -CONFIG_INPUT_MODE_SYNCHRONOUS=y - -# ========== Logging ========== -# RTT log backend: DROP mode (not BLOCK) — when no RTT host is connected the -# buffer is always full; BLOCK mode sleeps 20ms per message with irq_lock held, -# disrupting BLE timing and cascading into buffer exhaustion deadlocks. -CONFIG_LOG_BACKEND_RTT_MODE_DROP=y - -# Silence USB CH9 control-transfer spam (dozens of INF lines during enumeration). -# WRN keeps real USB errors visible. -CONFIG_USBD_LOG_LEVEL_WRN=y - -# ========== Power Management ========== -CONFIG_POWEROFF=y - -# ========== LoRa Power Saving ========== -# RX duty cycle defaults are in Kconfig: -# ON for companion + SX1262/LLCC68 (safe, saves 60-70% RX current) -# OFF for repeaters (latency > battery) and LR1110 (mid-preamble bug) -# Override at runtime via CLI "set rxduty on/off". - -# ========== ZephCore Log Levels ========== -# Defaults are INF for all modules (Kconfig default — no explicit =y needed). -# Override per-module on command line if needed: -# -DCONFIG_ZEPHCORE_BLE_LOG_LEVEL_DBG=y (BLE adapter only) -# -DCONFIG_ZEPHCORE_MAIN_LOG_LEVEL_DBG=y (mesh, companion, basechat, utils) +# ZephCore Common Configuration +# Included by ALL boards regardless of MCU (nRF52, nRF54L, ESP32, MG24, etc.) +# Contains application-level settings and platform-agnostic BLE/storage/radio config. +# +# Platform-specific configs (nrf52_common.conf, esp32_common.conf, etc.) only +# contain overrides and additions unique to that platform. + +# ========== Core Settings ========== +CONFIG_MAIN_STACK_SIZE=8192 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=8192 +CONFIG_EVENTS=y + +CONFIG_CPP=y +CONFIG_STD_CPP17=y + +# ========== Printf Formatting ========== +# Enable floating point support in printf/sprintf (required for CLI) +CONFIG_CBPRINTF_FP_SUPPORT=y + +# ========== Crypto (PSA) ========== +# Required for mesh encryption (AES-ECB, SHA256, HMAC) +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_PSA_CRYPTO_C=y +CONFIG_PSA_WANT_ALG_SHA_256=y +CONFIG_PSA_WANT_ALG_ECB_NO_PADDING=y +CONFIG_PSA_WANT_KEY_TYPE_AES=y +CONFIG_PSA_WANT_ALG_HMAC=y +CONFIG_PSA_WANT_KEY_TYPE_HMAC=y + +# ========== Stack Protection ========== +CONFIG_HW_STACK_PROTECTION=y +CONFIG_THREAD_NAME=y + +# ========== Hardware Basics ========== +CONFIG_ADC=y +CONFIG_HWINFO=y +CONFIG_REBOOT=y + +# ========== LoRa ========== +CONFIG_LORA=y +CONFIG_LORA_MODULE_BACKEND_NATIVE=y +CONFIG_REGULATOR=y + +# ========== Display Subsystem ========== +# Display and CFB are auto-enabled by ZEPHCORE_UI_DISPLAY (Kconfig select) +# when "zephyr,display" chosen node exists in the board's devicetree. +# No need to set CONFIG_DISPLAY or CONFIG_CHARACTER_FRAMEBUFFER here. + +# Heap baseline — display boards override for larger framebuffers. +CONFIG_HEAP_MEM_POOL_SIZE=2048 + +# ========== Sensor Subsystem ========== +# Sensors are auto-detected at runtime via I2C scan +CONFIG_SENSOR=y +CONFIG_I2C=y + +# ========== GNSS Subsystem ========== +# Driver auto-selected from board DTS compatible (zero overhead if no GNSS in DT): +# quectel,lc76g -> Quectel LCx6G driver +# luatos,air530z -> LuatOS Air530Z driver +# gnss-nmea-generic -> passive NMEA parser +CONFIG_GNSS=y +CONFIG_MODEM_MODULES=y + +# ========== BLE Stack (common to ALL platforms) ========== +CONFIG_BT=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_ZEPHYR_NUS=y +CONFIG_BT_ZEPHYR_NUS_DEFAULT_INSTANCE=n +CONFIG_BT_DEVICE_NAME="MeshCore" +CONFIG_BT_DEVICE_NAME_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_MAX=29 +CONFIG_BT_DEVICE_NAME_GATT_WRITABLE=y +CONFIG_BT_DEVICE_APPEARANCE=0 +CONFIG_BT_MAX_CONN=1 + +# SMP: MITM passkey, bonding, enforce bonding +CONFIG_BT_SMP=y +CONFIG_BT_SMP_ENFORCE_MITM=y +CONFIG_BT_APP_PASSKEY=y +CONFIG_BT_BONDABLE=y +CONFIG_BT_BONDING_REQUIRED=y +CONFIG_BT_MAX_PAIRED=5 +CONFIG_BT_KEYS_OVERWRITE_OLDEST=y + +# Connection parameter update — disabled because we apply conn params +# manually after initial sync completes (zephcore_ble_conn_params_ready). +# The auto-update would fire too early and disrupt channel/contact sync. +CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=n + +# MTU max (controller limit 251, L2CAP MTU 247, ATT payload 244) +CONFIG_BT_BUF_ACL_RX_SIZE=251 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_L2CAP_TX_MTU=247 + +# BLE TX buffers — default 3 is too low, causes system workqueue deadlock +# when BLE activity bursts (DLE + param update + ATT) exhaust all buffers +# and bt_hci_cmd_alloc(K_FOREVER) blocks the cooperative syswq forever. +CONFIG_BT_BUF_ACL_TX_COUNT=12 +CONFIG_BT_L2CAP_TX_BUF_COUNT=12 +CONFIG_BT_CONN_TX_MAX=12 + +# BLE RX thread stack — default 1200 too small for ATT handlers + logging + asserts +CONFIG_BT_RX_STACK_SIZE=2048 + +# Data Length Extension update support (host side) +CONFIG_BT_USER_DATA_LEN_UPDATE=y + +# PHY update callback — lets us log the negotiated PHY and sequence DLE +# after the PHY procedure completes (avoids LL procedure collision). +# +# NOTE: BT_USER_PHY_UPDATE disables BT_AUTO_PHY_UPDATE (Kconfig default). +# We intentionally do NOT set BT_AUTO_PHY_UPDATE — peripheral-initiated +# PHY updates cause iOS disconnects. The phone (central) initiates PHY +# update and le_phy_updated fires regardless. Coded PHY can be requested +# manually after security is established (future enhancement). +CONFIG_BT_USER_PHY_UPDATE=y + +# Privacy disabled — Android's Flutter BLE plugin fails to connect to +# RPA-advertised devices from app context (system BT settings works fine). +# Arduino MeshCore doesn't use RPA either. Actual link security comes from +# SMP pairing (passkey + SC + MITM + bonding), not address privacy. +# CONFIG_BT_PRIVACY=y +# NOTE: SC_PAIR_ONLY intentionally NOT set — Windows can't handle SC passkey +# pairing (never prompts for PIN). Allowing both Legacy and SC lets Windows +# pair with Legacy while iOS/Android use SC. + +# Disable Extended Advertising (ALL boards) +# Some controllers (MG24, ESP32) auto-select ext adv PDUs. +# Web Bluetooth (Chrome) can't discover devices using ext adv PDUs. +# Legacy ADV_IND works universally with all BLE scanners and web apps. +CONFIG_BT_EXT_ADV=n + +# Device Information Service (Apple requirement) +CONFIG_BT_DIS=y +CONFIG_BT_DIS_MANUF_NAME=y +CONFIG_BT_DIS_MANUF_NAME_STR="ZephCore" +CONFIG_BT_DIS_MODEL_NUMBER=y +CONFIG_BT_DIS_MODEL_NUMBER_STR="ZephCore" +CONFIG_BT_DIS_FW_REV=y +CONFIG_BT_DIS_FW_REV_STR="1.13.0" +CONFIG_BT_DIS_SW_REV=y +CONFIG_BT_DIS_SW_REV_STR="Zephyr" +CONFIG_BT_DIS_PNP=n + +# Disable GATT Caching (Robust Caching / Database Hash) +# With caching enabled (Kconfig default), Zephyr silently drops ATT requests +# from "change-unaware" clients after the GATT database changes. This breaks +# service discovery on phones that enable Robust Caching (modern iOS/Android). +# Arduino SoftDevice has no GATT caching — disabling matches that behavior. +CONFIG_BT_GATT_CACHING=n + +# Persistent bonds (NVS) +CONFIG_BT_SETTINGS=y +CONFIG_SETTINGS_RUNTIME=y + +# ========== Flash & Storage (common to ALL platforms) ========== +CONFIG_FLASH=y +CONFIG_FLASH_MAP=y +CONFIG_FLASH_PAGE_LAYOUT=y +CONFIG_SETTINGS=y + +# BLE bonds via file-based settings on LittleFS (all platforms) +CONFIG_NVS=n +CONFIG_SETTINGS_NVS=n +CONFIG_SETTINGS_FILE=y +CONFIG_SETTINGS_FILE_PATH="/lfs/settings" + +# LittleFS for DataStore +CONFIG_FILE_SYSTEM=y +CONFIG_FILE_SYSTEM_LITTLEFS=y +CONFIG_FS_LITTLEFS_NUM_FILES=8 +CONFIG_FS_LITTLEFS_NUM_DIRS=4 +CONFIG_FS_LITTLEFS_CACHE_SIZE=256 +CONFIG_FILE_SYSTEM_MKFS=y + +# ========== Input Subsystem ========== +CONFIG_INPUT=y +CONFIG_INPUT_EVENT_DUMP=n +# Synchronous mode: callbacks run in reporting context (GPIO ISR / syswq) +# instead of a dedicated 1KB input thread. Saves a thread stack. +CONFIG_INPUT_MODE_SYNCHRONOUS=y + +# ========== Logging ========== +# RTT log backend: DROP mode (not BLOCK) — when no RTT host is connected the +# buffer is always full; BLOCK mode sleeps 20ms per message with irq_lock held, +# disrupting BLE timing and cascading into buffer exhaustion deadlocks. +CONFIG_LOG_BACKEND_RTT_MODE_DROP=y + +# Silence USB CH9 control-transfer spam (dozens of INF lines during enumeration). +# WRN keeps real USB errors visible. +CONFIG_USBD_LOG_LEVEL_WRN=y + +# ========== Power Management ========== +CONFIG_POWEROFF=y + +# ========== LoRa Power Saving ========== +# RX duty cycle defaults are in Kconfig: +# ON for companion + SX1262/LLCC68 (safe, saves 60-70% RX current) +# OFF for repeaters (latency > battery) and LR1110 (mid-preamble bug) +# Override at runtime via CLI "set rxduty on/off". + +# ========== ZephCore Log Levels ========== +# Defaults are INF for all modules (Kconfig default — no explicit =y needed). +# Override per-module on command line if needed: +# -DCONFIG_ZEPHCORE_BLE_LOG_LEVEL_DBG=y (BLE adapter only) +# -DCONFIG_ZEPHCORE_MAIN_LOG_LEVEL_DBG=y (mesh, companion, basechat, utils)