diff --git a/esphome/components/esp32_ble/ble.cpp b/esphome/components/esp32_ble/ble.cpp index 24566e8f6d..a77496540d 100644 --- a/esphome/components/esp32_ble/ble.cpp +++ b/esphome/components/esp32_ble/ble.cpp @@ -322,23 +322,19 @@ void ESP32BLE::loop() { } else if (gap_event == ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT || gap_event == ESP_GAP_BLE_SCAN_START_COMPLETE_EVT || gap_event == ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT) { - // Create temporary param for scan complete events - esp_ble_gap_cb_param_t param; - memset(¶m, 0, sizeof(param)); + // All three scan complete events have the same structure with just status + // We can create a minimal structure that matches their layout + struct { + esp_bt_status_t status; + } scan_complete_param; - // Set the appropriate status field based on event type - if (gap_event == ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT) { - param.scan_param_cmpl.status = ble_event->event_.gap.scan_complete.status; - } else if (gap_event == ESP_GAP_BLE_SCAN_START_COMPLETE_EVT) { - param.scan_start_cmpl.status = ble_event->event_.gap.scan_complete.status; - } else if (gap_event == ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT) { - param.scan_stop_cmpl.status = ble_event->event_.gap.scan_complete.status; - } + scan_complete_param.status = ble_event->event_.gap.scan_complete.status; - this->real_gap_event_handler_(gap_event, ¶m); + // Cast is safe because all three event structures start with status + this->real_gap_event_handler_(gap_event, (esp_ble_gap_cb_param_t *) &scan_complete_param); } else { - // Fallback for unexpected events (uses full param copy) - this->real_gap_event_handler_(gap_event, &ble_event->event_.gap.gap_param); + // Unexpected GAP event - log and drop + ESP_LOGW(TAG, "Unexpected GAP event type: %d", gap_event); } break; } @@ -357,6 +353,13 @@ void ESP32BLE::loop() { void ESP32BLE::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { static constexpr size_t MAX_BLE_QUEUE_SIZE = SCAN_RESULT_BUFFER_SIZE * 2; + // Only queue the 4 GAP events we actually handle + if (event != ESP_GAP_BLE_SCAN_RESULT_EVT && event != ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT && + event != ESP_GAP_BLE_SCAN_START_COMPLETE_EVT && event != ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT) { + ESP_LOGW(TAG, "Ignoring unexpected GAP event type: %d", event); + return; + } + if (global_ble->ble_events_.size() >= MAX_BLE_QUEUE_SIZE) { ESP_LOGW(TAG, "BLE event queue full (%d), dropping GAP event %d", MAX_BLE_QUEUE_SIZE, event); return; diff --git a/esphome/components/esp32_ble/ble_event.h b/esphome/components/esp32_ble/ble_event.h index 7b1af08d54..03c86f09e9 100644 --- a/esphome/components/esp32_ble/ble_event.h +++ b/esphome/components/esp32_ble/ble_event.h @@ -48,9 +48,8 @@ class BLEEvent { break; default: - // For any other GAP events, copy the full param - // This is a safety fallback but shouldn't happen in normal operation - memcpy(&this->event_.gap.gap_param, p, sizeof(esp_ble_gap_cb_param_t)); + // We only handle 4 GAP event types, others are dropped + // This should never happen in normal operation break; } }; @@ -106,10 +105,10 @@ class BLEEvent { esp_bt_status_t status; } scan_complete; // 1 byte - // Fallback for unexpected events (shouldn't be used) - esp_ble_gap_cb_param_t gap_param; + // We only handle 4 GAP event types, no need for full fallback + // If we ever get an unexpected event, we'll just drop it in ble.cpp }; - } gap; // ~80 bytes instead of 400+ + } gap; // ~73 bytes (size of BLEScanResult) // NOLINTNEXTLINE(readability-identifier-naming) struct gattc_event { @@ -124,7 +123,7 @@ class BLEEvent { esp_gatt_if_t gatts_if; esp_ble_gatts_cb_param_t gatts_param; } gatts; // ~68 bytes - } event_; // Union size is now ~80 bytes (largest member) + } event_; // Union size is now ~73 bytes (BLEScanResult is largest) std::vector data{}; // For GATTC/GATTS data @@ -140,7 +139,7 @@ class BLEEvent { const BLEScanResult &scan_result() const { return event_.gap.scan_result; } esp_bt_status_t scan_complete_status() const { return event_.gap.scan_complete.status; } }; -// Total size: ~110 bytes instead of 440 bytes! +// Total size: ~100 bytes instead of 440 bytes! } // namespace esp32_ble } // namespace esphome