Address review: check prefer-conn-params, pace the retry drain

- Both esp_ble_gap_set_prefer_conn_params calls route through
  check_and_log_error_ like the class this PR replaces did; a rejected
  preference leaves the link on the controller default interval, which
  is exactly the WiFi-coex failure the shared constants exist to avoid,
  so it must be visible in logs
- The connections-free retry moves below the 100 ms gate so a full TCP
  buffer is retried at the loop cadence instead of every iteration
This commit is contained in:
J. Nick Koston
2026-08-09 15:15:33 -05:00
parent d586a6c8d4
commit b0f753a7a2
2 changed files with 15 additions and 11 deletions
@@ -129,11 +129,13 @@ void BluedroidGattClient::tracker_connect_() {
this->set_state(ClientState::CONNECTING);
if (this->connection_type_ == ConnectionType::V3_WITHOUT_CACHE) {
// Fast params for the discovery phase; stepped down at SEARCH_CMPL.
esp_ble_gap_set_prefer_conn_params(this->remote_bda_, FAST_MIN_CONN_INTERVAL, FAST_MAX_CONN_INTERVAL, 0,
FAST_CONN_TIMEOUT);
this->check_and_log_error_("esp_ble_gap_set_prefer_conn_params",
esp_ble_gap_set_prefer_conn_params(this->remote_bda_, FAST_MIN_CONN_INTERVAL,
FAST_MAX_CONN_INTERVAL, 0, FAST_CONN_TIMEOUT));
} else {
esp_ble_gap_set_prefer_conn_params(this->remote_bda_, MEDIUM_MIN_CONN_INTERVAL, MEDIUM_MAX_CONN_INTERVAL, 0,
MEDIUM_CONN_TIMEOUT);
this->check_and_log_error_("esp_ble_gap_set_prefer_conn_params",
esp_ble_gap_set_prefer_conn_params(this->remote_bda_, MEDIUM_MIN_CONN_INTERVAL,
MEDIUM_MAX_CONN_INTERVAL, 0, MEDIUM_CONN_TIMEOUT));
}
auto ret = esp_ble_gattc_open(this->gattc_if_, this->remote_bda_,
static_cast<esp_ble_addr_type_t>(this->remote_addr_type_), true);
@@ -476,13 +476,6 @@ void BluetoothProxy::loop() {
this->connections_[i]->process_pending_services();
}
#endif
if (this->connections_free_pending_ && this->api_connection_ != nullptr) {
// Resend a dropped slot-state update once the TCP buffer drains; the
// advertisement-only arm answers DISCONNECT requests with this message
// too, so the drain compiles on every proxy build.
this->connections_free_pending_ = false;
this->send_connections_free(this->api_connection_);
}
// Run advertisement flush / scanner-state poll every 100ms
uint32_t now = App.get_loop_component_start_time();
@@ -490,6 +483,15 @@ void BluetoothProxy::loop() {
return;
this->last_advertisement_flush_time_ = now;
if (this->connections_free_pending_ && this->api_connection_ != nullptr) {
// Resend a dropped slot-state update, paced by the 100 ms gate so the
// retry does not hammer the congestion it exists to survive; the
// advertisement-only arm answers DISCONNECT requests with this message
// too, so the drain compiles on every proxy build.
this->connections_free_pending_ = false;
this->send_connections_free(this->api_connection_);
}
if (!api::global_api_server->is_connected() || this->api_connection_ == nullptr) {
#ifdef BLUETOOTH_CONNECTION_HAS_GATT
// The API subscriber is gone: tear down any connections it left behind