Files
firmware/variants/native/portduino
James Rich 0e4d67c657 Add the BLE advertisement mesh bearer for ESP32 and nRF52
A second broadcast transport beside LoRa, carried in BLE extended
advertisements: each node advertises a mesh packet as manufacturer data
and scans for its peers' bursts, with no connection between them. It is
registered with the transport registry as TRANSPORT_BLE_ADV and enabled
by ProtocolFlags.BLE_BROADCAST in network.enabled_protocols. Off by
default and compiled only into envs that opt in, so nothing changes for
an existing build.

BLEMeshHandler holds the platform-independent half: framing, the ingress
guards mirrored from UdpMulticastHandler, the transmit ring and the peer
table. ESP32BLEMesh and NRF52BLEMesh drive the two BLE stacks. The nRF52
side polls nrf52BluetoothReady rather than being called, because
NRF52Bluetooth::setup() can run before main() has constructed the
handler. A scan needs a central link, which the shared linker script's
RAM origin cannot afford, so the nRF52 central is behind
BLE_MESH_NRF52_CENTRAL for the env that ships the re-based script.

On ESP32 the transport needs CONFIG_BT_NIMBLE_EXT_ADV, and IDF's NimBLE
compiles the legacy advertising API out once that is set: every
ble_gap_adv_* call returns BLE_HS_ENOTSUP, and the Arduino wrapper has
no extended equivalent. So under BLE_MESH_USE_EXT_ADV the phone API's
own advertisement moves to ext-adv instance 0 as a legacy ADV_IND,
identical on air to what the wrapper produced, chained to the wrapper's
private GAP handler so its subscription bookkeeping still sees the phone
link. The mesh burst takes instance 1.

Two ESP32 changes ride along. A one-time clear of the NimBLE bond store
under HAS_BLE_MESH, because NimBLE was seen to fail to come up after
flipping between builds with different BLE configs, which is this
feature's hazard. And on the S3 and C3 the default PHY is pinned to 1M
for every build of those targets: the controller asserts in its remote
PHY-update handler (esp-idf#15311) when an Apple central moves the link
to 2M, and ble_gap_set_default_le_phy() is compiled out of the prebuilt
host, so the HCI command is sent directly once the host has synced.

test_ble_mesh covers the handler on native, which is why portduino
defines HAS_BLE_MESH: nothing is instantiated there at runtime. The
suite constructs a NodeDB for the self-echo check, so it declares the
default pref writes in test/state-manifest.tsv like every suite that does.

The generated nanopb headers are not part of this change. The
update_protobufs workflow supplies them once the protobufs PR carrying
the enums merges.
2026-10-12 19:34:28 -05:00
..
2026-07-16 18:35:33 -05:00
2026-07-01 19:01:27 -05:00