[core] Use MAC address size constants in BLE components (#18252)

This commit is contained in:
Jesse Hills
2026-08-11 14:21:03 +12:00
committed by GitHub
parent eab9a47aa2
commit 8728aaa616
22 changed files with 63 additions and 56 deletions
+2 -2
View File
@@ -23,6 +23,7 @@
#include "esphome/core/application.h"
#include "esphome/core/entity_base.h"
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#include "esphome/core/version.h"
#ifdef USE_PROVISIONING
@@ -1849,8 +1850,7 @@ bool APIConnection::send_device_info_response_() {
#endif
#ifdef USE_BLUETOOTH_PROXY
resp.bluetooth_proxy_feature_flags = bluetooth_proxy::global_bluetooth_proxy->get_feature_flags();
// Stack buffer for Bluetooth MAC address (XX:XX:XX:XX:XX:XX\0 = 18 bytes)
char bluetooth_mac[18];
char bluetooth_mac[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
bluetooth_proxy::global_bluetooth_proxy->get_bluetooth_mac_address_pretty(bluetooth_mac);
resp.bluetooth_mac_address = StringRef(bluetooth_mac);
#endif
+6 -6
View File
@@ -116,7 +116,7 @@ void BK72xxBLE::enqueue_scan_report(const uint8_t *mac, int8_t rssi, uint8_t add
this->report_queue_.increment_dropped_count();
return;
}
memcpy(report->mac, mac, 6);
memcpy(report->mac, mac, MAC_ADDRESS_SIZE);
report->rssi = rssi;
report->addr_type = addr_type;
report->evt_type = evt_type;
@@ -230,7 +230,7 @@ void BK72xxBLE::loop() {
ESP_LOGW(TAG, "Dropped %u scan reports due to queue overflow", dropped);
}
void BK72xxBLE::get_mac_lsb_first(uint8_t out[6]) const {
void BK72xxBLE::get_mac_lsb_first(uint8_t out[MAC_ADDRESS_SIZE]) const {
for (int i = 0; i < 6; i++)
out[i] = this->ble_mac_[i];
}
@@ -263,7 +263,7 @@ void BK72xxBLE::resolve_mac_() {
}
}
if (nonzero) {
memcpy(this->ble_mac_, common_default_bdaddr.addr, 6);
memcpy(this->ble_mac_, common_default_bdaddr.addr, MAC_ADDRESS_SIZE);
return;
}
#endif
@@ -275,10 +275,10 @@ void BK72xxBLE::resolve_mac_() {
// (verified against the BK7231N BLE-5.1 and BK7252N/BK7238 BLE-5.2 SDK sources), so it
// matches on every device, including the last-byte == 0xFF edge that a 24-bit increment
// would carry differently.
uint8_t wifi_mac[6];
uint8_t wifi_mac[MAC_ADDRESS_SIZE];
get_mac_address_raw(wifi_mac); // MSB-first
const uint8_t ble[6] = {wifi_mac[0], wifi_mac[1], wifi_mac[2],
wifi_mac[3], wifi_mac[4], static_cast<uint8_t>(wifi_mac[5] + 1)};
const uint8_t ble[MAC_ADDRESS_SIZE] = {wifi_mac[0], wifi_mac[1], wifi_mac[2],
wifi_mac[3], wifi_mac[4], static_cast<uint8_t>(wifi_mac[5] + 1)};
// Store LSB-first to match recv_adv_t adv_addr ordering.
for (int i = 0; i < 6; i++)
this->ble_mac_[i] = ble[5 - i];
+10 -10
View File
@@ -40,8 +40,8 @@ struct ScanParams {
/// One advertisement report from the controller.
struct BLEScanReport {
uint8_t mac[6]; // LSB-first, as the controller delivers it
int8_t rssi; // signed dBm
uint8_t mac[MAC_ADDRESS_SIZE]; // LSB-first, as the controller delivers it
int8_t rssi; // signed dBm
uint8_t addr_type;
// GAPM report info byte (recv_adv_t.evt_type): bits 0-2 report type
// (1 = legacy adv, 3 = legacy scan response), bit 5 scannable — lets the
@@ -83,7 +83,7 @@ class BK72xxBLE final : public Component {
void set_enable_on_boot(bool enable_on_boot) { this->enable_on_boot_ = enable_on_boot; }
/// Controller BLE address, least-significant octet first (BLE convention).
void get_mac_lsb_first(uint8_t out[6]) const;
void get_mac_lsb_first(uint8_t out[MAC_ADDRESS_SIZE]) const;
#ifdef BK72XX_BLE_SCAN_LISTENER_COUNT
/// Register a consumer for scan reports (delivered on the main task via loop()).
@@ -135,13 +135,13 @@ class BK72xxBLE final : public Component {
esphome::EventPool<BLEScanReport, MAX_SCAN_REPORT_QUEUE_SIZE - 1> report_pool_;
// Largest-to-smallest: padding only at the tail, absorbed by future byte fields.
uint32_t last_advance_ms_{0};
uint32_t pending_since_ms_{0}; // bring-up budget anchor; refilled on request change
uint32_t teardown_since_ms_{0}; // unfinished teardown episode start; 0 = none
uint32_t teardown_stuck_log_ms_{0}; // last stuck-teardown ERROR; re-logged each TEARDOWN_STUCK_ERROR_MS
int last_release_err_{0}; // SDK code of the episode's last failed release; 0 = none
ScanParams requested_{}; // latched by scan_start()
ScanParams applied_{}; // last params we commanded; mismatch with requested_ restarts
uint8_t ble_mac_[6]{0}; // LSB-first (BLE convention)
uint32_t pending_since_ms_{0}; // bring-up budget anchor; refilled on request change
uint32_t teardown_since_ms_{0}; // unfinished teardown episode start; 0 = none
uint32_t teardown_stuck_log_ms_{0}; // last stuck-teardown ERROR; re-logged each TEARDOWN_STUCK_ERROR_MS
int last_release_err_{0}; // SDK code of the episode's last failed release; 0 = none
ScanParams requested_{}; // latched by scan_start()
ScanParams applied_{}; // last params we commanded; mismatch with requested_ restarts
uint8_t ble_mac_[MAC_ADDRESS_SIZE]{0}; // LSB-first (BLE convention)
uint8_t scan_activity_idx_{INVALID_ACTIVITY_IDX};
bool scan_wanted_{false}; // the latched request is to scan (vs stopped)
bool release_warned_{false}; // gates the release WARN; widens the pump gate
@@ -116,8 +116,8 @@ class BK72xxBLETracker : public Component,
bool request_scan_mode(bool active);
// The controller stores the address LSB-first (BLE convention); the contract
// wants printable (MSB-first) order.
void get_adapter_mac(uint8_t out[6]) {
uint8_t mac[6];
void get_adapter_mac(uint8_t out[MAC_ADDRESS_SIZE]) {
uint8_t mac[MAC_ADDRESS_SIZE];
this->parent_->get_mac_lsb_first(mac);
for (int i = 0; i < 6; i++)
out[i] = mac[5 - i];
@@ -137,7 +137,7 @@ void ESPBTDevice::parse_scan_rst(const esp32_ble::BLEScanResult &scan_result) {
// BLEScanResult's bda is most-significant octet first; the neutral ingest
// takes the BLE controller (LSB-first) order, so reverse — address_uint64()/
// address_str_to() then produce exactly the historical esp32 values.
uint8_t mac_lsb_first[6];
uint8_t mac_lsb_first[MAC_ADDRESS_SIZE];
for (uint8_t i = 0; i < 6; i++)
mac_lsb_first[i] = scan_result.bda[5 - i];
this->from_scan_result(mac_lsb_first, scan_result.rssi, scan_result.ble_addr_type, scan_result.ble_adv,
@@ -241,7 +241,7 @@ class ESPBTDevice {
// the 2-byte element header); every in-tree tracker scans legacy PDUs only.
static constexpr uint8_t MAX_ADV_NAME_LEN = 29;
uint8_t address_[6]{0};
uint8_t address_[MAC_ADDRESS_SIZE]{0};
uint8_t address_type_{0};
int rssi_{0};
// Fixed buffer instead of std::string: no per-advertisement heap churn on
@@ -2,6 +2,8 @@
#ifdef USE_BLE_SCAN_RESPONSE_MERGER
#include "esphome/core/helpers.h"
#include <cstring>
namespace esphome::ble_device_base {
@@ -27,7 +29,7 @@ void ScanResponseMerger::stash_adv(const uint8_t *mac, int8_t rssi, uint8_t addr
free_slot = &p;
continue;
}
if (p.addr_type == addr_type && memcmp(p.mac, mac, 6) == 0) {
if (p.addr_type == addr_type && memcmp(p.mac, mac, MAC_ADDRESS_SIZE) == 0) {
// Same device advertised again before its scan response arrived — deliver
// the previous advertisement (its scan response is not coming) and reuse
// the slot, so no frame is ever lost.
@@ -47,7 +49,7 @@ void ScanResponseMerger::stash_adv(const uint8_t *mac, int8_t rssi, uint8_t addr
}
slot->used = true;
this->pending_count_++;
memcpy(slot->mac, mac, 6);
memcpy(slot->mac, mac, MAC_ADDRESS_SIZE);
slot->addr_type = addr_type;
slot->rssi = rssi;
slot->data_len = (data_len <= sizeof(slot->data)) ? data_len : sizeof(slot->data);
@@ -61,7 +63,7 @@ void ScanResponseMerger::submit_scan_rsp(const uint8_t *mac, int8_t rssi, uint8_
// hottest caller.
if (this->pending_count_ != 0) {
for (auto &p : this->pending_adv_) {
if (p.used && p.addr_type == addr_type && memcmp(p.mac, mac, 6) == 0) {
if (p.used && p.addr_type == addr_type && memcmp(p.mac, mac, MAC_ADDRESS_SIZE) == 0) {
// Append in place: the slot is released on delivery, so its 62-byte
// buffer (legacy adv + scan response) holds the merged frame directly.
const uint8_t room = sizeof(p.data) - p.data_len;
@@ -120,7 +120,7 @@ class ScanResponseMerger {
// as ESP-IDF delivers on ESP32.
struct PendingAdv {
bool used{false};
uint8_t mac[6];
uint8_t mac[MAC_ADDRESS_SIZE];
uint8_t addr_type;
int8_t rssi;
uint8_t data_len; // <= sizeof(data)
@@ -21,7 +21,7 @@ void BluetoothConnection::set_address(uint64_t address) {
this->address_str_[0] = '\0';
return;
}
uint8_t mac[6];
uint8_t mac[MAC_ADDRESS_SIZE];
ble_device_base::uint64_to_mac_msb_first(address, mac);
format_mac_addr_upper(mac, this->address_str_);
}
@@ -5,6 +5,7 @@
#if defined(USE_RP2040_BLE) && defined(USE_BLE_GATT_CLIENT)
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#include <BluetoothLock.h>
@@ -1098,7 +1099,7 @@ int RP2GattClient::update_connection_params(uint16_t min_interval, uint16_t max_
}
conn_err_t unpair_device(uint64_t address) {
uint8_t mac[6];
uint8_t mac[MAC_ADDRESS_SIZE];
ble_device_base::uint64_to_mac_msb_first(address, mac);
bool found = false;
BluetoothLock lock;
@@ -140,7 +140,7 @@ void BluetoothProxy::dump_config() {
// Print configured facts. dump_config runs right after setup, before the
// radio is up, so live scan state would always read "stopped" here — the
// loop's BluetoothScannerStateResponse carries the changing value instead.
char mac_str[18];
char mac_str[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
this->get_bluetooth_mac_address_pretty(mac_str);
const char *mac_out = mac_str[0] != '\0' ? mac_str : "unavailable (adapter not up yet)";
const char *scan_mode = this->configured_scan_active_ ? "active" : "passive";
@@ -10,6 +10,7 @@
#include "esphome/components/api/api_pb2.h"
#include "esphome/core/automation.h"
#include "esphome/core/component.h"
#include "esphome/core/helpers.h"
#include "esphome/components/bluetooth_connection/bluetooth_connection.h"
@@ -201,8 +202,8 @@ class BluetoothProxy final : public Component {
return flags;
}
void get_bluetooth_mac_address_pretty(std::span<char, 18> output) {
uint8_t mac[6] = {};
void get_bluetooth_mac_address_pretty(std::span<char, MAC_ADDRESS_PRETTY_BUFFER_SIZE> output) {
uint8_t mac[MAC_ADDRESS_SIZE] = {};
this->hub_->get_adapter_mac(mac);
// Unavailable -> empty string: some hubs (rp2040's BTstack) only learn
// the address once the link layer is up, and report all-zero until then.
+5 -5
View File
@@ -674,21 +674,21 @@ void ESP32BLE::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gat
}
#endif
void ESP32BLE::get_mac_msb_first(uint8_t out[6]) const {
void ESP32BLE::get_mac_msb_first(uint8_t out[MAC_ADDRESS_SIZE]) const {
// The running stack owns the address (on hosted controllers it lives in
// the remote chip's efuse); null before init becomes all-zero.
const uint8_t *mac = esp_bt_dev_get_address();
if (mac != nullptr) {
memcpy(out, mac, 6);
memcpy(out, mac, MAC_ADDRESS_SIZE);
} else {
memset(out, 0, 6);
memset(out, 0, MAC_ADDRESS_SIZE);
}
}
float ESP32BLE::get_setup_priority() const { return setup_priority::BLUETOOTH; }
void ESP32BLE::dump_config() {
uint8_t mac_address[6];
uint8_t mac_address[MAC_ADDRESS_SIZE];
this->get_mac_msb_first(mac_address);
if (mac_address_is_valid(mac_address)) {
const char *io_capability_s;
@@ -713,7 +713,7 @@ void ESP32BLE::dump_config() {
break;
}
char mac_s[18];
char mac_s[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
format_mac_addr_upper(mac_address, mac_s);
ESP_LOGCONFIG(TAG,
"BLE:\n"
+1 -1
View File
@@ -109,7 +109,7 @@ class ESP32BLE final : public Component {
void loop() override;
void dump_config() override;
/// Adapter MAC in printable (MSB-first) order; all-zero until the stack is up.
void get_mac_msb_first(uint8_t out[6]) const;
void get_mac_msb_first(uint8_t out[MAC_ADDRESS_SIZE]) const;
float get_setup_priority() const override;
void set_name(const char *name) { this->name_ = name; }
@@ -200,7 +200,7 @@ class ESP32BLETracker final : public Component,
return {/* active_scan = */ true, /* merges_scan_response = */ true, /* gatt = */ true,
/* scan_mode_switch = */ false};
}
void get_adapter_mac(uint8_t out[6]) { this->parent_->get_mac_msb_first(out); }
void get_adapter_mac(uint8_t out[MAC_ADDRESS_SIZE]) { this->parent_->get_mac_msb_first(out); }
bool scan_running() { return this->scanner_state_ == ScannerState::RUNNING; }
bool scan_active() { return this->scan_active_; }
// The mode is driven through this tracker's own API (see get_capabilities);
+3 -3
View File
@@ -236,7 +236,7 @@ static void ble_scan_callback(void *param) {
// downstream the value is used exactly like on ESP32.
const int8_t raw = info->rssi;
memcpy(slot->mac, info->trans_addr, 6);
memcpy(slot->mac, info->trans_addr, MAC_ADDRESS_SIZE);
slot->rssi = (raw > 20) ? static_cast<int8_t>(-raw) : raw;
slot->addr_type = info->trans_addr_type;
slot->is_scan_response = report_type == GAPM_REPORT_TYPE_SCAN_RSP_LEG;
@@ -407,7 +407,7 @@ void LN882HBLE::resolve_mac_() {
ESP_LOGW(TAG, "BLE address KV unavailable; deriving address from WiFi MAC");
}
if (!have_unique_addr) {
uint8_t wifi_mac[6] = {0};
uint8_t wifi_mac[MAC_ADDRESS_SIZE] = {0};
get_mac_address_raw(wifi_mac); // MSB-first
// Reverse into controller (LSB-first) order, then BLE = WiFi + 1: increment
// the NIC low byte (addr[0] once reversed), no carry, OUI unchanged — the
@@ -421,7 +421,7 @@ void LN882HBLE::resolve_mac_() {
ESP_LOGD(TAG, "MAC derived (WiFi+1) and stored");
}
}
memcpy(this->ble_mac_, bt_addr.addr, 6);
memcpy(this->ble_mac_, bt_addr.addr, MAC_ADDRESS_SIZE);
}
// ---------------------------------------------------------------------------
+3 -3
View File
@@ -23,8 +23,8 @@ enum class BLEComponentState : uint8_t {
/// One scan report from the controller, decoded from the SDK's rw-task event
/// (RSSI already sign-corrected).
struct BLEScanReport {
uint8_t mac[6]; // as the controller delivers it (LSB-first)
int8_t rssi; // signed dBm (-127..+20)
uint8_t mac[MAC_ADDRESS_SIZE]; // as the controller delivers it (LSB-first)
int8_t rssi; // signed dBm (-127..+20)
uint8_t addr_type;
bool is_scan_response; // report is a scan response (active scan)
bool scannable; // advertisement may be followed by a scan response
@@ -138,7 +138,7 @@ class LN882HBLE final : public Component {
// Reports rejected by the legacy-only filter (rw-task producer, main-task
// consumer via exchange in loop()).
std::atomic<uint16_t> rejected_reports_{0};
uint8_t ble_mac_[6]{0}; // controller (LSB-first) order, as ln_bd_addr_t stores it
uint8_t ble_mac_[MAC_ADDRESS_SIZE]{0}; // controller (LSB-first) order, as ln_bd_addr_t stores it
BLEComponentState state_{BLEComponentState::STATE_OFF};
bool enable_on_boot_{false};
bool scanning_{false}; // controller scan running (re-entry guard for scan_start)
@@ -90,8 +90,8 @@ class LN882HBLETracker : public Component,
}
// The controller stores the address LSB-first (BLE convention); the contract
// wants printable (MSB-first) order.
void get_adapter_mac(uint8_t out[6]) {
uint8_t mac[6];
void get_adapter_mac(uint8_t out[MAC_ADDRESS_SIZE]) {
uint8_t mac[MAC_ADDRESS_SIZE];
this->parent_->get_mac_lsb_first(mac);
for (int i = 0; i < 6; i++)
out[i] = mac[5 - i];
+6 -3
View File
@@ -2,6 +2,7 @@
#ifdef USE_RP2040_BLE
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#include <BluetoothLock.h>
@@ -180,7 +181,7 @@ void RP2040BLE::packet_handler(uint8_t type, uint16_t channel, uint8_t *packet,
// ESPHome main loop: bounded copy into the lock-free queue only.
bd_addr_t addr; // accessor returns printable (MSB-first) order
gap_event_advertising_report_get_address(packet, addr);
uint8_t mac_lsb[6];
uint8_t mac_lsb[MAC_ADDRESS_SIZE];
reverse_bd_addr(addr, mac_lsb); // LSB-first, the BLE convention consumers expect
global_ble->enqueue_scan_report_(mac_lsb, static_cast<int8_t>(gap_event_advertising_report_get_rssi(packet)),
gap_event_advertising_report_get_address_type(packet),
@@ -206,7 +207,7 @@ void RP2040BLE::enqueue_scan_report_(const uint8_t *mac_lsb_first, int8_t rssi,
this->report_queue_.increment_dropped_count();
return;
}
memcpy(report->mac, mac_lsb_first, 6);
memcpy(report->mac, mac_lsb_first, MAC_ADDRESS_SIZE);
report->rssi = rssi;
report->addr_type = addr_type;
report->adv_event_type = adv_event_type;
@@ -217,7 +218,9 @@ void RP2040BLE::enqueue_scan_report_(const uint8_t *mac_lsb_first, int8_t rssi,
}
// NOLINTEND(clang-analyzer-unix.Malloc)
void RP2040BLE::get_mac_msb_first(uint8_t out[6]) const { memcpy(out, this->ble_mac_, 6); }
void RP2040BLE::get_mac_msb_first(uint8_t out[MAC_ADDRESS_SIZE]) const {
memcpy(out, this->ble_mac_, MAC_ADDRESS_SIZE);
}
bool RP2040BLE::scan_start(uint16_t interval, uint16_t window, bool active) {
if (!this->is_active()) {
+4 -4
View File
@@ -25,8 +25,8 @@ enum class BLEComponentState : uint8_t {
/// One advertisement report from the controller.
struct BLEScanReport {
uint8_t mac[6]; // LSB-first, as the controller delivers it
int8_t rssi; // signed dBm
uint8_t mac[MAC_ADDRESS_SIZE]; // LSB-first, as the controller delivers it
int8_t rssi; // signed dBm
uint8_t addr_type;
uint8_t adv_event_type; // GAP advertising event type (ADV_IND .. SCAN_RSP); lets a merger tell the two apart
uint8_t data_len; // bytes valid in data[]
@@ -77,7 +77,7 @@ class RP2040BLE final : public Component {
/// (LSB-first) order, hence the explicit names. All zeros until the stack
/// reports ACTIVE (BTstack reads the address from the controller during
/// power-up).
void get_mac_msb_first(uint8_t out[6]) const;
void get_mac_msb_first(uint8_t out[MAC_ADDRESS_SIZE]) const;
#ifdef RP2040_BLE_SCAN_LISTENER_COUNT
/// Register a consumer for scan reports (delivered on the main loop via loop()).
@@ -135,7 +135,7 @@ class RP2040BLE final : public Component {
btstack_packet_callback_registration_t hci_event_callback_registration_{};
btstack_packet_callback_registration_t sm_event_callback_registration_{};
uint8_t ble_mac_[6]{0}; // printable (MSB-first) order; zeros until ACTIVE
uint8_t ble_mac_[MAC_ADDRESS_SIZE]{0}; // printable (MSB-first) order; zeros until ACTIVE
BLEComponentState state_{BLEComponentState::STATE_OFF};
bool enable_on_boot_{true};
bool btstack_initialized_{false};
@@ -71,7 +71,7 @@ class RP2BLETracker : public Component,
}
// The controller stores the address in printable (MSB-first) order, which is
// exactly what the contract wants.
void get_adapter_mac(uint8_t out[6]) { this->parent_->get_mac_msb_first(out); }
void get_adapter_mac(uint8_t out[MAC_ADDRESS_SIZE]) { this->parent_->get_mac_msb_first(out); }
bool scan_running() { return this->scan_running_; }
bool scan_active() { return this->scan_active_; }
bool request_scan_mode(bool active);
+2 -2
View File
@@ -293,7 +293,7 @@ bool decrypt_xiaomi_payload(std::vector<uint8_t> &raw, const uint8_t *bindkey, c
return false;
}
uint8_t mac_reverse[6] = {0};
uint8_t mac_reverse[MAC_ADDRESS_SIZE] = {0};
mac_reverse[5] = (uint8_t) (address >> 40);
mac_reverse[4] = (uint8_t) (address >> 32);
mac_reverse[3] = (uint8_t) (address >> 24);
@@ -358,7 +358,7 @@ bool decrypt_xiaomi_payload(std::vector<uint8_t> &raw, const uint8_t *bindkey, c
#endif
if (!decrypt_ok) {
uint8_t mac_address[6] = {0};
uint8_t mac_address[MAC_ADDRESS_SIZE] = {0};
memcpy(mac_address, mac_reverse + 5, 1);
memcpy(mac_address + 1, mac_reverse + 4, 1);
memcpy(mac_address + 2, mac_reverse + 3, 1);