diff --git a/src/NimBLEAdvertisedDevice.cpp b/src/NimBLEAdvertisedDevice.cpp index 4377ed286..69b17f27b 100644 --- a/src/NimBLEAdvertisedDevice.cpp +++ b/src/NimBLEAdvertisedDevice.cpp @@ -38,6 +38,7 @@ NimBLEAdvertisedDevice::NimBLEAdvertisedDevice(const ble_gap_event* event, uint8 m_callbackSent{0}, m_advLength{event->ext_disc.length_data}, m_isLegacyAdv{!!(event->ext_disc.props & BLE_HCI_ADV_LEGACY_MASK)}, + m_dataStatus{event->ext_disc.data_status}, m_sid{event->ext_disc.sid}, m_primPhy{event->ext_disc.prim_phy}, m_secPhy{event->ext_disc.sec_phy}, @@ -60,7 +61,16 @@ NimBLEAdvertisedDevice::NimBLEAdvertisedDevice(const ble_gap_event* event, uint8 void NimBLEAdvertisedDevice::update(const ble_gap_event* event, uint8_t eventType) { # if CONFIG_BT_NIMBLE_EXT_ADV const auto& disc = event->ext_disc; - m_isLegacyAdv = disc.props & BLE_HCI_ADV_LEGACY_MASK; + if (m_dataStatus == BLE_GAP_EXT_ADV_DATA_STATUS_INCOMPLETE) { + m_payload.reserve(m_advLength + disc.length_data); + m_payload.insert(m_payload.end(), disc.data, disc.data + disc.length_data); + m_dataStatus = disc.data_status; + m_advLength = m_payload.size(); + return; + } + + m_dataStatus = disc.data_status; + m_isLegacyAdv = disc.props & BLE_HCI_ADV_LEGACY_MASK; # else const auto& disc = event->disc; # endif @@ -617,6 +627,18 @@ uint8_t NimBLEAdvertisedDevice::getSecondaryPhy() const { uint16_t NimBLEAdvertisedDevice::getPeriodicInterval() const { return m_periodicItvl; } // getPeriodicInterval + +/** + * @brief Get the advertisement data status. + * @return The advertisement data status. + * One of: + * * BLE_GAP_EXT_ADV_DATA_STATUS_COMPLETE (0) - Complete extended advertising data + * * BLE_GAP_EXT_ADV_DATA_STATUS_INCOMPLETE (1) - Incomplete extended advertising data, more to come + * * BLE_GAP_EXT_ADV_DATA_STATUS_TRUNCATED (2) - Incomplete extended advertising data, no more to come + */ +uint8_t NimBLEAdvertisedDevice::getDataStatus() const { + return m_dataStatus; +} // getDataStatus # endif uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, size_t* data_loc) const { @@ -730,7 +752,7 @@ std::string NimBLEAdvertisedDevice::toString() const { * @brief Get the length of the advertisement data in the payload. * @return The number of bytes in the payload that is from the advertisement. */ -uint8_t NimBLEAdvertisedDevice::getAdvLength() const { +uint16_t NimBLEAdvertisedDevice::getAdvLength() const { return m_advLength; } diff --git a/src/NimBLEAdvertisedDevice.h b/src/NimBLEAdvertisedDevice.h index 2348e8aee..a71316595 100644 --- a/src/NimBLEAdvertisedDevice.h +++ b/src/NimBLEAdvertisedDevice.h @@ -69,7 +69,7 @@ class NimBLEAdvertisedDevice { NimBLEAddress getTargetAddress(uint8_t index = 0) const; uint8_t getTargetAddressCount() const; int8_t getTXPower() const; - uint8_t getAdvLength() const; + uint16_t getAdvLength() const; uint8_t getAddressType() const; bool isAdvertisingService(const NimBLEUUID& uuid) const; bool haveAppearance() const; @@ -92,6 +92,7 @@ class NimBLEAdvertisedDevice { uint8_t getPrimaryPhy() const; uint8_t getSecondaryPhy() const; uint16_t getPeriodicInterval() const; + uint8_t getDataStatus() const; # endif operator NimBLEAddress() const; @@ -161,10 +162,11 @@ class NimBLEAdvertisedDevice { uint8_t m_advType{}; int8_t m_rssi{}; uint8_t m_callbackSent{}; - uint8_t m_advLength{}; + uint16_t m_advLength{}; # if CONFIG_BT_NIMBLE_EXT_ADV bool m_isLegacyAdv{}; + uint8_t m_dataStatus{}; uint8_t m_sid{}; uint8_t m_primPhy{}; uint8_t m_secPhy{}; diff --git a/src/NimBLEExtAdvertising.cpp b/src/NimBLEExtAdvertising.cpp index d3a020610..3df38952a 100644 --- a/src/NimBLEExtAdvertising.cpp +++ b/src/NimBLEExtAdvertising.cpp @@ -616,6 +616,11 @@ bool NimBLEExtAdvertisement::setFlags(uint8_t flag) { * @return True if successful. */ bool NimBLEExtAdvertisement::setManufacturerData(const uint8_t* data, size_t length) { + if (length > 0xFF - 1) { + NIMBLE_LOGE(LOG_TAG, "Manufacturer data too long!"); + return false; + } + uint8_t header[2]; header[0] = length + 1; header[1] = BLE_HS_ADV_TYPE_MFG_DATA; @@ -652,6 +657,11 @@ bool NimBLEExtAdvertisement::setManufacturerData(const std::vector& dat * @return True if successful. */ bool NimBLEExtAdvertisement::setURI(const std::string& uri) { + if (uri.length() > 0xFF - 1) { + NIMBLE_LOGE(LOG_TAG, "URI too long!"); + return false; + } + uint8_t header[2]; header[0] = uri.length() + 1; header[1] = BLE_HS_ADV_TYPE_URI; @@ -670,6 +680,11 @@ bool NimBLEExtAdvertisement::setURI(const std::string& uri) { * @return True if successful. */ bool NimBLEExtAdvertisement::setName(const std::string& name, bool isComplete) { + if (name.length() > 0xFF - 1) { + NIMBLE_LOGE(LOG_TAG, "Name too long!"); + return false; + } + uint8_t header[2]; header[0] = name.length() + 1; header[1] = isComplete ? BLE_HS_ADV_TYPE_COMP_NAME : BLE_HS_ADV_TYPE_INCOMP_NAME; @@ -917,8 +932,12 @@ bool NimBLEExtAdvertisement::setServices(bool complete, uint8_t size, const std: */ bool NimBLEExtAdvertisement::setServiceData(const NimBLEUUID& uuid, const uint8_t* data, size_t length) { uint8_t uuidBytes = uuid.bitSize() / 8; - uint8_t sDataLen = 2 + uuidBytes + length; + if (length + uuidBytes + 2 > 0xFF) { + NIMBLE_LOGE(LOG_TAG, "Service data too long!"); + return false; + } + uint8_t sDataLen = 2 + uuidBytes + length; if (m_payload.size() + sDataLen > CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN) { return false; } diff --git a/src/NimBLEScan.cpp b/src/NimBLEScan.cpp index 713c84a19..6b30145b6 100644 --- a/src/NimBLEScan.cpp +++ b/src/NimBLEScan.cpp @@ -117,13 +117,22 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) { NIMBLE_LOGI(LOG_TAG, "New advertiser: %s", advertisedAddress.toString().c_str()); } else { advertisedDevice->update(event, event_type); - if (isLegacyAdv && event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) { - NIMBLE_LOGI(LOG_TAG, "Scan response from: %s", advertisedAddress.toString().c_str()); - } else { - NIMBLE_LOGI(LOG_TAG, "Duplicate; updated: %s", advertisedAddress.toString().c_str()); + if (isLegacyAdv) { + if (event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) { + NIMBLE_LOGI(LOG_TAG, "Scan response from: %s", advertisedAddress.toString().c_str()); + } else { + NIMBLE_LOGI(LOG_TAG, "Duplicate; updated: %s", advertisedAddress.toString().c_str()); + } } } +# if CONFIG_BT_NIMBLE_EXT_ADV + if (advertisedDevice->getDataStatus() == BLE_GAP_EXT_ADV_DATA_STATUS_INCOMPLETE) { + NIMBLE_LOGD(LOG_TAG, "EXT ADV data incomplete, waiting for more"); + return 0; + } +# endif + if (!advertisedDevice->m_callbackSent) { advertisedDevice->m_callbackSent++; pScan->m_pScanCallbacks->onDiscovered(advertisedDevice); diff --git a/src/nimconfig.h b/src/nimconfig.h index e130c834c..f863df767 100644 --- a/src/nimconfig.h +++ b/src/nimconfig.h @@ -51,7 +51,7 @@ // #define CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES 1 /** @brief Un-comment to set the max extended advertising data size (Range: 31 - 1650) */ -// #define CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN 251 +// #define CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN 1650 /** @brief Un-comment to enable periodic advertising */ // #define CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV 1 @@ -391,7 +391,10 @@ defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3) # define CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES 1 # endif # if !defined(CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN) -# define CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN 251 +# define CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN 1650 +# endif +# if !defined(CONFIG_BT_NIMBLE_EXT_ADV_MAX_SIZE) +# define CONFIG_BT_NIMBLE_EXT_ADV_MAX_SIZE CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN # endif #endif