Emit the materializer define only for the backend that has one

The registry entry now carries its materializer gate, so rp2 builds stop
receiving a Bluedroid define. Also: parent before the capacity check in
register_gatt_node (neutral parity) and BluedroidServiceTable is
non-copyable (owning raw pointer).
This commit is contained in:
J. Nick Koston
2026-08-19 10:30:43 -05:00
parent baf57195e2
commit 5f11c430cc
3 changed files with 12 additions and 2 deletions
@@ -141,6 +141,9 @@ bool BLEClient::all_nodes_established_() {
#ifdef USE_BLE_CLIENT_GATT_NODES
void BLEClient::register_gatt_node(BLEClientNode *node) {
// Parent before the capacity check so a dropped node still has a usable
// parent() (neutral-engine parity).
node->set_ble_client_parent(this);
if (this->gatt_nodes_.size() == ESPHOME_BLE_CLIENT_MAX_NODES) {
// push_back past capacity is a silent no-op; an undersized slot count
// must be loud at boot, not an unresolvable node at runtime.
@@ -126,6 +126,8 @@ class _PlatformBackend:
register: Callable[[cg.MockObj, ConfigType], Awaitable[None]]
# Selects the backend's alias-ladder arm (order-independent arms).
define: str
# The backend's on-demand materializer gate, when it has one.
materializer_define: str | None = None
# The single registry of platforms with a GATT client backend; a platform
@@ -137,6 +139,7 @@ _PLATFORM_BACKENDS: dict[str, _PlatformBackend] = {
_esp32_schema_fragment,
_esp32_register,
"USE_BLE_GATT_BACKEND_BLUEDROID",
materializer_define="USE_BLUEDROID_GATT_SERVICE_TABLE",
),
PLATFORM_RP2: _PlatformBackend(
RP2GattClient, _rp2_schema_fragment, _rp2_register, "USE_BLE_GATT_BACKEND_RP2"
@@ -254,8 +257,8 @@ async def new_gatt_backend(
entry = _backend_entry()
ble_device_base.request_gatt_client()
cg.add_define(entry.define)
if service_table:
cg.add_define("USE_BLUEDROID_GATT_SERVICE_TABLE")
if service_table and entry.materializer_define is not None:
cg.add_define(entry.materializer_define)
backend = cg.new_Pvariable(config[CONF_BACKEND_ID])
# The backend is the slot's real Component: component keys from the
# connection entry (setup_priority, ...) apply to it. Consumers whose own
@@ -18,6 +18,10 @@ namespace esphome::bluetooth_connection {
class BluedroidServiceTable {
public:
~BluedroidServiceTable() { this->free(); }
// Owns storage_; a copy would double-free.
BluedroidServiceTable() = default;
BluedroidServiceTable(const BluedroidServiceTable &) = delete;
BluedroidServiceTable &operator=(const BluedroidServiceTable &) = delete;
/// The service count build() requires: the stack's PRIMARY+SECONDARY
/// attribute totals, never the SEARCH_RES event count.