From 10d589162b382ca3cb89a1dce9a0933e50edddad Mon Sep 17 00:00:00 2001 From: h2zero Date: Fri, 12 Jul 2024 20:42:53 -0600 Subject: [PATCH] [Breaking] Refactor NimBLEUUID. * msbFirst parameter has been removed from constructor as it was unnecessary, caller should reverse the data first or call the new `reverseByteOrder` method after. * `getNative` method replaced with `getBase` which returns a read-only pointer to the UUID size underlying. * Added `reverseByteOrder` method, this will reverse the bytes of the UUID, which can be useful for advertising/logging. * Added `getValue` method, which returns a read-only `uint8_t` pointer to the UUID value. * Removed `m_valueSet` member variable, `bitSize()` can be used as a replacement. * General code cleanup. --- src/NimBLEAdvertisedDevice.cpp | 6 +- src/NimBLEAdvertising.cpp | 82 +++----- src/NimBLEBeacon.cpp | 6 +- src/NimBLECharacteristic.cpp | 2 +- src/NimBLEClient.cpp | 2 +- src/NimBLEDescriptor.cpp | 2 +- src/NimBLEEddystoneTLM.cpp | 6 +- src/NimBLEEddystoneURL.cpp | 6 +- src/NimBLEExtAdvertising.cpp | 47 ++--- src/NimBLERemoteCharacteristic.cpp | 2 +- src/NimBLERemoteService.cpp | 2 +- src/NimBLEServer.cpp | 4 +- src/NimBLEService.cpp | 8 +- src/NimBLEUUID.cpp | 310 ++++++++++++----------------- src/NimBLEUUID.h | 62 +++--- 15 files changed, 237 insertions(+), 310 deletions(-) diff --git a/src/NimBLEAdvertisedDevice.cpp b/src/NimBLEAdvertisedDevice.cpp index dea7127..e5a8fc6 100644 --- a/src/NimBLEAdvertisedDevice.cpp +++ b/src/NimBLEAdvertisedDevice.cpp @@ -320,7 +320,7 @@ std::string NimBLEAdvertisedDevice::getServiceData(const NimBLEUUID& uuid) const while (data_loc < pl_size) { const ble_hs_adv_field* field = reinterpret_cast(&m_payload[data_loc]); - if (bytes == uuid_bytes && NimBLEUUID(field->value, bytes, false) == uuid) { + if (bytes == uuid_bytes && NimBLEUUID(field->value, bytes) == uuid) { const char* field_data = reinterpret_cast(field->value + bytes); return std::string(field_data, field->length - bytes - 1); } @@ -344,7 +344,7 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID(uint8_t index) const { if (data_loc != ULONG_MAX) { const ble_hs_adv_field* field = reinterpret_cast(&m_payload[data_loc]); if (field->length >= bytes) { - return NimBLEUUID(field->value, bytes, false); + return NimBLEUUID(field->value, bytes); } } @@ -436,7 +436,7 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) const { } if (field->length > uuid_bytes * index) { - return NimBLEUUID(field->value + uuid_bytes * (index - 1), uuid_bytes, false); + return NimBLEUUID(field->value + uuid_bytes * (index - 1), uuid_bytes); } } diff --git a/src/NimBLEAdvertising.cpp b/src/NimBLEAdvertising.cpp index cc04422..ca8acf7 100644 --- a/src/NimBLEAdvertising.cpp +++ b/src/NimBLEAdvertising.cpp @@ -196,8 +196,7 @@ void NimBLEAdvertising::setURI(const std::string &uri) { void NimBLEAdvertising::setServiceData(const NimBLEUUID &uuid, const std::string &data) { switch (uuid.bitSize()) { case 16: { - std::vector((uint8_t*)&uuid.getNative()->u16.value, - (uint8_t*)&uuid.getNative()->u16.value + 2).swap(m_svcData16); + std::vector(uuid.getValue(), uuid.getValue() + 2).swap(m_svcData16); m_svcData16.insert(m_svcData16.end(), data.begin(), data.end()); m_advData.svc_data_uuid16 = (uint8_t*)&m_svcData16[0]; m_advData.svc_data_uuid16_len = (data.length() > 0) ? m_svcData16.size() : 0; @@ -205,8 +204,7 @@ void NimBLEAdvertising::setServiceData(const NimBLEUUID &uuid, const std::string } case 32: { - std::vector((uint8_t*)&uuid.getNative()->u32.value, - (uint8_t*)&uuid.getNative()->u32.value + 4).swap(m_svcData32); + std::vector(uuid.getValue(), uuid.getValue() + 4).swap(m_svcData32); m_svcData32.insert(m_svcData32.end(), data.begin(), data.end()); m_advData.svc_data_uuid32 = (uint8_t*)&m_svcData32[0]; m_advData.svc_data_uuid32_len = (data.length() > 0) ? m_svcData32.size() : 0; @@ -214,8 +212,7 @@ void NimBLEAdvertising::setServiceData(const NimBLEUUID &uuid, const std::string } case 128: { - std::vector(uuid.getNative()->u128.value, - uuid.getNative()->u128.value + 16).swap(m_svcData128); + std::vector(uuid.getValue(), uuid.getValue() + 16).swap(m_svcData128); m_svcData128.insert(m_svcData128.end(), data.begin(), data.end()); m_advData.svc_data_uuid128 = (uint8_t*)&m_svcData128[0]; m_advData.svc_data_uuid128_len = (data.length() > 0) ? m_svcData128.size() : 0; @@ -489,7 +486,7 @@ bool NimBLEAdvertising::start(uint32_t duration, advCompleteCB_t advCompleteCB, payloadLen += (2 + BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN); for(auto &it : m_serviceUUIDs) { - if(it.getNative()->u.type == BLE_UUID_TYPE_16) { + if(it.bitSize() == BLE_UUID_TYPE_16) { int add = (m_advData.num_uuids16 > 0) ? 2 : 4; if((payloadLen + add) > BLE_HS_ADV_MAX_SZ){ m_advData.uuids16_is_complete = 0; @@ -497,18 +494,17 @@ bool NimBLEAdvertising::start(uint32_t duration, advCompleteCB_t advCompleteCB, } payloadLen += add; - if(nullptr == (m_advData.uuids16 = (ble_uuid16_t*)realloc((void*)m_advData.uuids16, - (m_advData.num_uuids16 + 1) * sizeof(ble_uuid16_t)))) + if(nullptr == (m_advData.uuids16 = reinterpret_cast(realloc((void*)m_advData.uuids16, + (m_advData.num_uuids16 + 1) * sizeof(ble_uuid16_t))))) { NIMBLE_LOGE(LOG_TAG, "Error, no mem"); return false; } memcpy((void*)&m_advData.uuids16[m_advData.num_uuids16], - &it.getNative()->u16, sizeof(ble_uuid16_t)); + reinterpret_cast(&it), sizeof(ble_uuid16_t)); m_advData.uuids16_is_complete = 1; m_advData.num_uuids16++; - } - if(it.getNative()->u.type == BLE_UUID_TYPE_32) { + } else if(it.bitSize() == BLE_UUID_TYPE_32) { int add = (m_advData.num_uuids32 > 0) ? 4 : 6; if((payloadLen + add) > BLE_HS_ADV_MAX_SZ){ m_advData.uuids32_is_complete = 0; @@ -516,18 +512,17 @@ bool NimBLEAdvertising::start(uint32_t duration, advCompleteCB_t advCompleteCB, } payloadLen += add; - if(nullptr == (m_advData.uuids32 = (ble_uuid32_t*)realloc((void*)m_advData.uuids32, - (m_advData.num_uuids32 + 1) * sizeof(ble_uuid32_t)))) + if(nullptr == (m_advData.uuids32 = reinterpret_cast(realloc((void*)m_advData.uuids32, + (m_advData.num_uuids32 + 1) * sizeof(ble_uuid32_t))))) { NIMBLE_LOGE(LOG_TAG, "Error, no mem"); return false; } memcpy((void*)&m_advData.uuids32[m_advData.num_uuids32], - &it.getNative()->u32, sizeof(ble_uuid32_t)); + reinterpret_cast(&it), sizeof(ble_uuid32_t)); m_advData.uuids32_is_complete = 1; m_advData.num_uuids32++; - } - if(it.getNative()->u.type == BLE_UUID_TYPE_128){ + } else if(it.bitSize() == BLE_UUID_TYPE_128){ int add = (m_advData.num_uuids128 > 0) ? 16 : 18; if((payloadLen + add) > BLE_HS_ADV_MAX_SZ){ m_advData.uuids128_is_complete = 0; @@ -535,14 +530,14 @@ bool NimBLEAdvertising::start(uint32_t duration, advCompleteCB_t advCompleteCB, } payloadLen += add; - if(nullptr == (m_advData.uuids128 = (ble_uuid128_t*)realloc((void*)m_advData.uuids128, - (m_advData.num_uuids128 + 1) * sizeof(ble_uuid128_t)))) + if(nullptr == (m_advData.uuids128 = reinterpret_cast(realloc((void*)m_advData.uuids128, + (m_advData.num_uuids128 + 1) * sizeof(ble_uuid128_t))))) { NIMBLE_LOGE(LOG_TAG, "Error, no mem"); return false; } memcpy((void*)&m_advData.uuids128[m_advData.num_uuids128], - &it.getNative()->u128, sizeof(ble_uuid128_t)); + reinterpret_cast(&it), sizeof(ble_uuid128_t)); m_advData.uuids128_is_complete = 1; m_advData.num_uuids128++; } @@ -961,21 +956,9 @@ void NimBLEAdvertisementData::setServices(const bool complete, const uint8_t siz for(auto &it : v_uuid){ if(it.bitSize() != size) { NIMBLE_LOGE(LOG_TAG, "Service UUID(%d) invalid", size); - return; + continue; } else { - switch(size) { - case 16: - uuids += std::string((char*)&it.getNative()->u16.value, 2); - break; - case 32: - uuids += std::string((char*)&it.getNative()->u32.value, 4); - break; - case 128: - uuids += std::string((char*)&it.getNative()->u128.value, 16); - break; - default: - return; - } + uuids += std::string(reinterpret_cast(it.getValue()), size / 8); } } @@ -989,35 +972,30 @@ void NimBLEAdvertisementData::setServices(const bool complete, const uint8_t siz * @param [in] data The data to be associated with the service data advertised. */ void NimBLEAdvertisementData::setServiceData(const NimBLEUUID &uuid, const std::string &data) { - char cdata[2]; - switch (uuid.bitSize()) { - case 16: { + uint8_t size = uuid.bitSize() / 8; + char cdata[2] = {static_cast(1 + size), BLE_HS_ADV_TYPE_SVC_DATA_UUID16}; + switch (size) { + case 2: { // [Len] [0x16] [UUID16] data - cdata[0] = data.length() + 3; - cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID16; // 0x16 - addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u16.value, 2) + data); break; } - - case 32: { - // [Len] [0x20] [UUID32] data - cdata[0] = data.length() + 5; - cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID32; // 0x20 - addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u32.value, 4) + data); - break; - } - - case 128: { + case 16: { // [Len] [0x21] [UUID128] data - cdata[0] = data.length() + 17; cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID128; // 0x21 - addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u128.value, 16) + data); + break; + } + + case 4: { + // [Len] [0x20] [UUID32] data + cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID32; // 0x20 break; } default: return; } + + addData(std::string(cdata, 2) + std::string(reinterpret_cast(uuid.getValue()), size) + data); } // setServiceData diff --git a/src/NimBLEBeacon.cpp b/src/NimBLEBeacon.cpp index df24ced..2c472e5 100644 --- a/src/NimBLEBeacon.cpp +++ b/src/NimBLEBeacon.cpp @@ -79,7 +79,7 @@ uint16_t NimBLEBeacon::getMinor() { * @return The UUID advertised. */ NimBLEUUID NimBLEBeacon::getProximityUUID() { - return NimBLEUUID(m_beaconData.proximityUUID, 16, true); + return NimBLEUUID(m_beaconData.proximityUUID, 16).reverseByteOrder(); } @@ -140,9 +140,7 @@ void NimBLEBeacon::setMinor(uint16_t minor) { void NimBLEBeacon::setProximityUUID(const NimBLEUUID &uuid) { NimBLEUUID temp_uuid = uuid; temp_uuid.to128(); - std::reverse_copy(temp_uuid.getNative()->u128.value, - temp_uuid.getNative()->u128.value + 16, - m_beaconData.proximityUUID); + std::reverse_copy(temp_uuid.getValue(), temp_uuid.getValue() + 16, m_beaconData.proximityUUID); } // setProximityUUID diff --git a/src/NimBLECharacteristic.cpp b/src/NimBLECharacteristic.cpp index 82aa20f..ba68a73 100644 --- a/src/NimBLECharacteristic.cpp +++ b/src/NimBLECharacteristic.cpp @@ -274,7 +274,7 @@ int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_han ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR ? "Read" : "Write"); uuid = ctxt->chr->uuid; - if(ble_uuid_cmp(uuid, &pCharacteristic->getUUID().getNative()->u) == 0){ + if(ble_uuid_cmp(uuid, pCharacteristic->getUUID().getBase()) == 0){ switch(ctxt->op) { case BLE_GATT_ACCESS_OP_READ_CHR: { ble_gap_conn_find(conn_handle, &peerInfo.m_desc); diff --git a/src/NimBLEClient.cpp b/src/NimBLEClient.cpp index 4f78452..0fbcbb4 100644 --- a/src/NimBLEClient.cpp +++ b/src/NimBLEClient.cpp @@ -814,7 +814,7 @@ bool NimBLEClient::retrieveServices(const NimBLEUUID *uuid_filter) { if(uuid_filter == nullptr) { rc = ble_gattc_disc_all_svcs(m_conn_id, NimBLEClient::serviceDiscoveredCB, &taskData); } else { - rc = ble_gattc_disc_svc_by_uuid(m_conn_id, &uuid_filter->getNative()->u, + rc = ble_gattc_disc_svc_by_uuid(m_conn_id, uuid_filter->getBase(), NimBLEClient::serviceDiscoveredCB, &taskData); } diff --git a/src/NimBLEDescriptor.cpp b/src/NimBLEDescriptor.cpp index a457782..c919126 100644 --- a/src/NimBLEDescriptor.cpp +++ b/src/NimBLEDescriptor.cpp @@ -169,7 +169,7 @@ int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle, ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC ? "Read" : "Write"); uuid = ctxt->chr->uuid; - if(ble_uuid_cmp(uuid, &pDescriptor->getUUID().getNative()->u) == 0){ + if(ble_uuid_cmp(uuid, pDescriptor->getUUID().getBase()) == 0){ switch(ctxt->op) { case BLE_GATT_ACCESS_OP_READ_DSC: { ble_gap_conn_find(conn_handle, &peerInfo.m_desc); diff --git a/src/NimBLEEddystoneTLM.cpp b/src/NimBLEEddystoneTLM.cpp index 1f48a16..d6a7657 100644 --- a/src/NimBLEEddystoneTLM.cpp +++ b/src/NimBLEEddystoneTLM.cpp @@ -176,7 +176,11 @@ void NimBLEEddystoneTLM::setData(const std::string &data) { * @param [in] l_uuid The UUID. */ void NimBLEEddystoneTLM::setUUID(const NimBLEUUID &l_uuid) { - beaconUUID = l_uuid.getNative()->u16.value; + if (l_uuid.bitSize() != 16) { + NIMBLE_LOGE(LOG_TAG, "UUID must be 16 bits"); + return; + } + beaconUUID = *reinterpret_cast(l_uuid.getValue()); } // setUUID diff --git a/src/NimBLEEddystoneURL.cpp b/src/NimBLEEddystoneURL.cpp index 73829d7..73fcb33 100644 --- a/src/NimBLEEddystoneURL.cpp +++ b/src/NimBLEEddystoneURL.cpp @@ -172,7 +172,11 @@ void NimBLEEddystoneURL::setData(const std::string &data) { * @param [in] l_uuid The UUID. */ void NimBLEEddystoneURL::setUUID(const NimBLEUUID &l_uuid) { - beaconUUID = l_uuid.getNative()->u16.value; + if (l_uuid.bitSize() != 16) { + NIMBLE_LOGE(LOG_TAG, "UUID must be 16 bits"); + return; + } + beaconUUID = *reinterpret_cast(l_uuid.getValue()); } // setUUID diff --git a/src/NimBLEExtAdvertising.cpp b/src/NimBLEExtAdvertising.cpp index 866e452..60575e0 100644 --- a/src/NimBLEExtAdvertising.cpp +++ b/src/NimBLEExtAdvertising.cpp @@ -761,21 +761,9 @@ void NimBLEExtAdvertisement::setServices(const bool complete, const uint8_t size for(auto &it : v_uuid){ if(it.bitSize() != size) { NIMBLE_LOGE(LOG_TAG, "Service UUID(%d) invalid", size); - return; + continue; } else { - switch(size) { - case 16: - uuids += std::string((char*)&it.getNative()->u16.value, 2); - break; - case 32: - uuids += std::string((char*)&it.getNative()->u32.value, 4); - break; - case 128: - uuids += std::string((char*)&it.getNative()->u128.value, 16); - break; - default: - return; - } + uuids += std::string(reinterpret_cast(it.getValue()), size / 8); } } @@ -789,35 +777,30 @@ void NimBLEExtAdvertisement::setServices(const bool complete, const uint8_t size * @param [in] data The data to be associated with the service data advertised. */ void NimBLEExtAdvertisement::setServiceData(const NimBLEUUID &uuid, const std::string &data) { - char cdata[2]; - switch (uuid.bitSize()) { - case 16: { + uint8_t size = uuid.bitSize() / 8; + char cdata[2] = {static_cast(1 + size), BLE_HS_ADV_TYPE_SVC_DATA_UUID16}; + switch (size) { + case 2: { // [Len] [0x16] [UUID16] data - cdata[0] = data.length() + 3; - cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID16; // 0x16 - addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u16.value, 2) + data); break; } - - case 32: { - // [Len] [0x20] [UUID32] data - cdata[0] = data.length() + 5; - cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID32; // 0x20 - addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u32.value, 4) + data); - break; - } - - case 128: { + case 16: { // [Len] [0x21] [UUID128] data - cdata[0] = data.length() + 17; cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID128; // 0x21 - addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u128.value, 16) + data); + break; + } + + case 4: { + // [Len] [0x20] [UUID32] data + cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID32; // 0x20 break; } default: return; } + + addData(std::string(cdata, 2) + std::string(reinterpret_cast(uuid.getValue()), size) + data); } // setServiceData diff --git a/src/NimBLERemoteCharacteristic.cpp b/src/NimBLERemoteCharacteristic.cpp index 35c191d..1678858 100644 --- a/src/NimBLERemoteCharacteristic.cpp +++ b/src/NimBLERemoteCharacteristic.cpp @@ -160,7 +160,7 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle, switch (rc) { case 0: { if (uuid_filter != nullptr) { - if (ble_uuid_cmp(&uuid_filter->getNative()->u, &dsc->uuid.u) != 0) { + if (ble_uuid_cmp(uuid_filter->getBase(), &dsc->uuid.u) != 0) { return 0; } else { rc = BLE_HS_EDONE; diff --git a/src/NimBLERemoteService.cpp b/src/NimBLERemoteService.cpp index 5a72fe3..51e6244 100644 --- a/src/NimBLERemoteService.cpp +++ b/src/NimBLERemoteService.cpp @@ -228,7 +228,7 @@ bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID *uuid_filter) rc = ble_gattc_disc_chrs_by_uuid(m_pClient->getConnId(), m_startHandle, m_endHandle, - &uuid_filter->getNative()->u, + uuid_filter->getBase(), NimBLERemoteService::characteristicDiscCB, &taskData); } diff --git a/src/NimBLEServer.cpp b/src/NimBLEServer.cpp index 4c5f84e..072605c 100644 --- a/src/NimBLEServer.cpp +++ b/src/NimBLEServer.cpp @@ -219,7 +219,7 @@ void NimBLEServer::start() { // with Notify / Indicate capabilities for event handling for(auto &svc : m_svcVec) { if(svc->m_removed == 0) { - rc = ble_gatts_find_svc(&svc->getUUID().getNative()->u, &svc->m_handle); + rc = ble_gatts_find_svc(svc->getUUID().getBase(), &svc->m_handle); if(rc != 0) { NIMBLE_LOGW(LOG_TAG, "GATT Server started without service: %s, Service %s", svc->getUUID().toString().c_str(), svc->isStarted() ? "missing" : "not started"); @@ -412,7 +412,7 @@ std::string NimBLEServer::getPeerNameInternal(uint16_t conn_handle, TaskHandle_t int rc = ble_gattc_read_by_uuid(conn_handle, 1, 0xffff, - ((ble_uuid_t*)&uuid), + &uuid.u, NimBLEServer::peerNameCB, taskData); if (rc != 0) { diff --git a/src/NimBLEService.cpp b/src/NimBLEService.cpp index 8055869..07b1e46 100644 --- a/src/NimBLEService.cpp +++ b/src/NimBLEService.cpp @@ -131,7 +131,7 @@ bool NimBLEService::start() { ble_gatt_dsc_def* pDsc_a = nullptr; svc[0].type = BLE_GATT_SVC_TYPE_PRIMARY; - svc[0].uuid = &m_uuid.getNative()->u; + svc[0].uuid = m_uuid.getBase(); svc[0].includes = NULL; int removedCount = 0; @@ -194,7 +194,7 @@ bool NimBLEService::start() { if((*dsc_it)->m_removed > 0) { continue; } - pDsc_a[d].uuid = &(*dsc_it)->m_uuid.getNative()->u; + pDsc_a[d].uuid = (*dsc_it)->m_uuid.getBase(); pDsc_a[d].att_flags = (*dsc_it)->m_properties; pDsc_a[d].min_key_size = 0; pDsc_a[d].access_cb = NimBLEDescriptor::handleGapEvent; @@ -206,7 +206,7 @@ bool NimBLEService::start() { pChr_a[i].descriptors = pDsc_a; } - pChr_a[i].uuid = &(*chr_it)->m_uuid.getNative()->u; + pChr_a[i].uuid = (*chr_it)->m_uuid.getBase(); pChr_a[i].access_cb = NimBLECharacteristic::handleGapEvent; pChr_a[i].arg = (*chr_it); pChr_a[i].flags = (*chr_it)->m_properties; @@ -248,7 +248,7 @@ bool NimBLEService::start() { */ uint16_t NimBLEService::getHandle() { if (m_handle == NULL_HANDLE) { - ble_gatts_find_svc(&getUUID().getNative()->u, &m_handle); + ble_gatts_find_svc(getUUID().getBase(), &m_handle); } return m_handle; } // getHandle diff --git a/src/NimBLEUUID.cpp b/src/NimBLEUUID.cpp index b14eae1..38c7903 100644 --- a/src/NimBLEUUID.cpp +++ b/src/NimBLEUUID.cpp @@ -15,21 +15,22 @@ #include "nimconfig.h" #if defined(CONFIG_BT_ENABLED) -#include "NimBLEUtils.h" -#include "NimBLEUUID.h" -#include "NimBLELog.h" +# include "NimBLEUtils.h" +# include "NimBLEUUID.h" +# include "NimBLELog.h" -#include - -static const char* LOG_TAG = "NimBLEUUID"; +# include +static const char* LOG_TAG = "NimBLEUUID"; +static const uint8_t ble_base_uuid[] = { + 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /** * @brief Create a UUID from a string. * - * Create a UUID from a string. There will be two possible stories here. Either the string represents - * a binary data field or the string represents a hex encoding of a UUID. - * For the hex encoding, here is an example: + * Create a UUID from a string. There will be two possible stories here. Either + * the string represents a binary data field or the string represents a hex + * encoding of a UUID. For the hex encoding, here is an example: * * ``` * "beb5483e-36e1-4688-b7f5-ea07361b26a8" @@ -41,104 +42,68 @@ static const char* LOG_TAG = "NimBLEUUID"; * * @param [in] value The string to build a UUID from. */ - NimBLEUUID::NimBLEUUID(const std::string &value) { - m_valueSet = true; +NimBLEUUID::NimBLEUUID(const std::string& value) { if (value.length() == 4) { - m_uuid.u.type = BLE_UUID_TYPE_16; - m_uuid.u16.value = strtoul(value.c_str(), NULL, 16); - } - else if (value.length() == 8) { - m_uuid.u.type = BLE_UUID_TYPE_32; - m_uuid.u32.value = strtoul(value.c_str(), NULL, 16); - } - else if (value.length() == 16) { - *this = NimBLEUUID((uint8_t*)value.data(), 16, true); - } - else if (value.length() == 36) { - // If the length of the string is 36 bytes then we will assume it is a long hex string in - // UUID format. - char * position = const_cast(value.c_str()); - uint32_t first = strtoul(position, &position, 16); - uint16_t second = strtoul(position + 1, &position, 16); - uint16_t third = strtoul(position + 1, &position, 16); - uint16_t fourth = strtoul(position + 1, &position, 16); - uint64_t fifth = strtoull(position + 1, NULL, 16); - *this = NimBLEUUID(first, second, third, (uint64_t(fourth) << 48) + fifth); - } - else { - m_valueSet = false; + m_uuid.u.type = BLE_UUID_TYPE_16; + m_uuid.u16.value = strtoul(value.c_str(), nullptr, 16); + } else if (value.length() == 8) { + m_uuid.u.type = BLE_UUID_TYPE_32; + m_uuid.u32.value = strtoul(value.c_str(), nullptr, 16); + } else if (value.length() == 16) { + memcpy(m_uuid.u128.value, &value[0], 16); + m_uuid.u.type = BLE_UUID_TYPE_128; + } else if (value.length() == 36) { + char* position; + uint64_t first_half = (strtoull(&value[0], &position, 16) << 32) + + (strtoull(position + 1, &position, 16) << 16) + strtoull(position + 1, &position, 16); + uint64_t second_half = (strtoull(position + 1, &position, 16) << 48) + strtoull(position + 1, nullptr, 16); + memcpy(m_uuid.u128.value + 8, &first_half, 8); + memcpy(m_uuid.u128.value, &second_half, 8); + m_uuid.u.type = BLE_UUID_TYPE_128; + } else { + NIMBLE_LOGE(LOG_TAG, "Invalid UUID length"); + m_uuid.u.type = 0; } } // NimBLEUUID(std::string) - /** * @brief Create a UUID from 2, 4, 16 bytes of memory. * @param [in] pData The pointer to the start of the UUID. * @param [in] size The size of the data. - * @param [in] msbFirst Is the MSB first in pData memory? */ -NimBLEUUID::NimBLEUUID(const uint8_t* pData, size_t size, bool msbFirst) { - uint8_t *uuidValue = nullptr; - - switch(size) { - case 2: - uuidValue = (uint8_t*)&m_uuid.u16.value; - m_uuid.u.type = BLE_UUID_TYPE_16; - break; - case 4: - uuidValue = (uint8_t*)&m_uuid.u32.value; - m_uuid.u.type = BLE_UUID_TYPE_32; - break; - case 16: - uuidValue = m_uuid.u128.value; - m_uuid.u.type = BLE_UUID_TYPE_128; - break; - default: - m_valueSet = false; - NIMBLE_LOGE(LOG_TAG, "Invalid UUID size"); - return; +NimBLEUUID::NimBLEUUID(const uint8_t* pData, size_t size) { + if (ble_uuid_init_from_buf(&m_uuid, pData, size)) { + NIMBLE_LOGE(LOG_TAG, "Invalid UUID size"); + m_uuid.u.type = 0; } - if (msbFirst) { - std::reverse_copy(pData, pData + size, uuidValue); - } else { - memcpy(uuidValue, pData, size); - } - m_valueSet = true; -} // NimBLEUUID - +} // NimBLEUUID(const uint8_t* pData, size_t size) /** * @brief Create a UUID from the 16bit value. * @param [in] uuid The 16bit short form UUID. */ NimBLEUUID::NimBLEUUID(uint16_t uuid) { - m_uuid.u.type = BLE_UUID_TYPE_16; - m_uuid.u16.value = uuid; - m_valueSet = true; -} // NimBLEUUID - + m_uuid.u.type = BLE_UUID_TYPE_16; + m_uuid.u16.value = uuid; +} // NimBLEUUID(uint16_t uuid) /** * @brief Create a UUID from the 32bit value. * @param [in] uuid The 32bit short form UUID. */ NimBLEUUID::NimBLEUUID(uint32_t uuid) { - m_uuid.u.type = BLE_UUID_TYPE_32; - m_uuid.u32.value = uuid; - m_valueSet = true; -} // NimBLEUUID - + m_uuid.u.type = BLE_UUID_TYPE_32; + m_uuid.u32.value = uuid; +} // NimBLEUUID(uint32_t uuid) /** * @brief Create a UUID from the native UUID. * @param [in] uuid The native UUID. */ NimBLEUUID::NimBLEUUID(const ble_uuid128_t* uuid) { - m_uuid.u.type = BLE_UUID_TYPE_128; + m_uuid.u.type = BLE_UUID_TYPE_128; memcpy(m_uuid.u128.value, uuid->value, 16); - m_valueSet = true; -} // NimBLEUUID - +} // NimBLEUUID(const ble_uuid128_t* uuid) /** * @brief Create a UUID from the 128bit value using hex parts instead of string, @@ -151,32 +116,47 @@ NimBLEUUID::NimBLEUUID(const ble_uuid128_t* uuid) { * @param [in] fourth The last 64bit of the UUID, combining the last 2 parts of the string equivalent */ NimBLEUUID::NimBLEUUID(uint32_t first, uint16_t second, uint16_t third, uint64_t fourth) { - m_uuid.u.type = BLE_UUID_TYPE_128; - memcpy(m_uuid.u128.value + 12, &first, 4); + m_uuid.u.type = BLE_UUID_TYPE_128; + memcpy(m_uuid.u128.value + 12, &first, 4); memcpy(m_uuid.u128.value + 10, &second, 2); - memcpy(m_uuid.u128.value + 8, &third, 2); - memcpy(m_uuid.u128.value, &fourth, 8); - m_valueSet = true; -} - + memcpy(m_uuid.u128.value + 8, &third, 2); + memcpy(m_uuid.u128.value, &fourth, 8); +} // NimBLEUUID(uint32_t first, uint16_t second, uint16_t third, uint64_t fourth) /** - * @brief Creates an empty UUID. - */ -NimBLEUUID::NimBLEUUID() { - m_valueSet = false; -} // NimBLEUUID - - -/** - * @brief Get the number of bits in this uuid. - * @return The number of bits in the UUID. One of 16, 32 or 128. + * @brief Get the bit size of the UUID, 16, 32 or 128. + * @return The bit size of the UUID or 0 if not initialized. */ uint8_t NimBLEUUID::bitSize() const { - if (!m_valueSet) return 0; - return m_uuid.u.type; + return this->m_uuid.u.type; } // bitSize +/** + * @brief Get the uuid value. + * @return A pointer to the UUID value or nullptr if not initialized. + * @note This should be checked with `bitSize()` before accessing. + */ +const uint8_t* NimBLEUUID::getValue() const { + switch (bitSize()) { + case BLE_UUID_TYPE_16: + return reinterpret_cast(&m_uuid.u16.value); + case BLE_UUID_TYPE_32: + return reinterpret_cast(&m_uuid.u32.value); + case BLE_UUID_TYPE_128: + return m_uuid.u128.value; + default: + return nullptr; + } +} // getValue + +/** + * @brief Get a pointer to the NimBLE UUID base structure. + * @return A Read-only pointer to the NimBLE UUID base structure. + * @note The type value should be checked, if no 16, 32 or 128 then the UUID is not initialized. + */ +const ble_uuid_t* NimBLEUUID::getBase() const { + return &this->m_uuid.u; +} // getBase /** * @brief Compare a UUID against this UUID. @@ -184,10 +164,9 @@ uint8_t NimBLEUUID::bitSize() const { * @param [in] uuid The UUID to compare against. * @return True if the UUIDs are equal and false otherwise. */ -bool NimBLEUUID::equals(const NimBLEUUID &uuid) const { +bool NimBLEUUID::equals(const NimBLEUUID& uuid) const { return *this == uuid; -} - +} // equals /** * Create a NimBLEUUID from a string of the form: @@ -200,14 +179,14 @@ bool NimBLEUUID::equals(const NimBLEUUID &uuid) const { * * @param [in] uuid The string to create the UUID from. */ -NimBLEUUID NimBLEUUID::fromString(const std::string &uuid) { +NimBLEUUID NimBLEUUID::fromString(const std::string& uuid) { uint8_t start = 0; if (strstr(uuid.c_str(), "0x") != nullptr) { // If the string starts with 0x, skip those characters. start = 2; } - uint8_t len = uuid.length() - start; // Calculate the length of the string we are going to use. - if(len == 4) { + uint8_t len = uuid.length() - start; // Calculate the length of the string we are going to use. + if (len == 4) { uint16_t x = strtoul(uuid.substr(start, len).c_str(), NULL, 16); return NimBLEUUID(x); } else if (len == 8) { @@ -216,47 +195,29 @@ NimBLEUUID NimBLEUUID::fromString(const std::string &uuid) { } else if (len == 36) { return NimBLEUUID(uuid); } + return NimBLEUUID(); } // fromString - -/** - * @brief Get the native UUID value. - * @return The native UUID value or nullptr if not set. - */ -const ble_uuid_any_t* NimBLEUUID::getNative() const { - if (m_valueSet == false) { - NIMBLE_LOGD(LOG_TAG,"<< Return of un-initialized UUID!"); - return nullptr; - } - return &m_uuid; -} // getNative - - /** * @brief Convert a UUID to its 128 bit representation. * @details A UUID can be internally represented as 16bit, 32bit or the full 128bit. * This method will convert 16 or 32bit representations to the full 128bit. * @return The NimBLEUUID converted to 128bit. */ -const NimBLEUUID &NimBLEUUID::to128() { +const NimBLEUUID& NimBLEUUID::to128() { // If we either don't have a value or are already a 128 bit UUID, nothing further to do. - if (!m_valueSet || m_uuid.u.type == BLE_UUID_TYPE_128) { - return *this; - } - - // If we are 16 bit or 32 bit, then set the other bytes of the UUID. - if (m_uuid.u.type == BLE_UUID_TYPE_16) { - *this = NimBLEUUID(m_uuid.u16.value, 0x0000, 0x1000, 0x800000805f9b34fb); - } - else if (m_uuid.u.type == BLE_UUID_TYPE_32) { - *this = NimBLEUUID(m_uuid.u32.value, 0x0000, 0x1000, 0x800000805f9b34fb); + if (bitSize() != BLE_UUID_TYPE_128) { + uint32_t val = bitSize() == BLE_UUID_TYPE_16 ? *reinterpret_cast(getValue()) + : *reinterpret_cast(getValue()); + memcpy(m_uuid.u128.value, &ble_base_uuid, sizeof(ble_base_uuid) - 4); + memcpy(m_uuid.u128.value + 12, &val, 4); + m_uuid.u.type = BLE_UUID_TYPE_128; } return *this; } // to128 - /** * @brief Convert 128 bit UUID to its 16 bit representation. * @details A UUID can be internally represented as 16bit, 32bit or the full 128bit. @@ -264,21 +225,16 @@ const NimBLEUUID &NimBLEUUID::to128() { * @return The NimBLEUUID converted to 16bit if successful, otherwise the original uuid. */ const NimBLEUUID& NimBLEUUID::to16() { - if (!m_valueSet || m_uuid.u.type == BLE_UUID_TYPE_16) { - return *this; - } - - if (m_uuid.u.type == BLE_UUID_TYPE_128) { - uint8_t base128[] = {0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x00, 0x00}; - if (memcmp(m_uuid.u128.value, base128, sizeof(base128)) == 0 ) { - *this = NimBLEUUID(*(uint16_t*)(m_uuid.u128.value + 12)); + if (bitSize() == BLE_UUID_TYPE_128) { + const uint8_t* val = getValue(); + if (memcmp(val, ble_base_uuid, sizeof(ble_base_uuid) - 4) == 0) { + m_uuid.u16.value = *reinterpret_cast(val + 12); + m_uuid.u.type = BLE_UUID_TYPE_16; } } return *this; -} - +} // to16 /** * @brief Get a string representation of the UUID. @@ -295,53 +251,55 @@ std::string NimBLEUUID::toString() const { return std::string(*this); } // toString +/** + * @brief Reverse the byte order of the UUID. + * @return The NimBLEUUID with the byte order reversed. + * @details This is useful when comparing UUIDs or when the advertisement data is reversed. + */ +const NimBLEUUID& NimBLEUUID::reverseByteOrder() { + if (bitSize() == BLE_UUID_TYPE_128) { + std::reverse(m_uuid.u128.value, m_uuid.u128.value + 16); + } else if (bitSize() == BLE_UUID_TYPE_32) { + m_uuid.u32.value = __builtin_bswap32(m_uuid.u32.value); + } else if (bitSize() == BLE_UUID_TYPE_16) { + m_uuid.u16.value = __builtin_bswap16(m_uuid.u16.value); + } + + return *this; +} // reverseByteOrder /** * @brief Convenience operator to check if this UUID is equal to another. */ -bool NimBLEUUID::operator ==(const NimBLEUUID & rhs) const { - if(m_valueSet && rhs.m_valueSet) { - if(m_uuid.u.type != rhs.m_uuid.u.type) { - uint8_t uuidBase[16] = { - 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, - 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; +bool NimBLEUUID::operator==(const NimBLEUUID& rhs) const { + if (this->bitSize() != rhs.bitSize()) { + uint8_t uuid128[sizeof(ble_base_uuid)]; + memcpy(uuid128, &ble_base_uuid, sizeof(ble_base_uuid)); + if (this->bitSize() == BLE_UUID_TYPE_128) { + memcpy(uuid128 + 12, rhs.getValue(), rhs.bitSize() == BLE_UUID_TYPE_16 ? 2 : 4); + return memcmp(this->getValue(), uuid128, sizeof(ble_base_uuid)) == 0; - if(m_uuid.u.type == BLE_UUID_TYPE_128){ - if(rhs.m_uuid.u.type == BLE_UUID_TYPE_16){ - memcpy(uuidBase+12, &rhs.m_uuid.u16.value, 2); - } else if (rhs.m_uuid.u.type == BLE_UUID_TYPE_32){ - memcpy(uuidBase+12, &rhs.m_uuid.u32.value, 4); - } - return memcmp(m_uuid.u128.value,uuidBase,16) == 0; - - } else if(rhs.m_uuid.u.type == BLE_UUID_TYPE_128) { - if(m_uuid.u.type == BLE_UUID_TYPE_16){ - memcpy(uuidBase+12, &m_uuid.u16.value, 2); - } else if (m_uuid.u.type == BLE_UUID_TYPE_32){ - memcpy(uuidBase+12, &m_uuid.u32.value, 4); - } - return memcmp(rhs.m_uuid.u128.value,uuidBase,16) == 0; - - } else { - return false; - } + } else if (rhs.bitSize() == BLE_UUID_TYPE_128) { + memcpy(uuid128 + 12, getValue(), this->bitSize() == BLE_UUID_TYPE_16 ? 2 : 4); + return memcmp(rhs.getValue(), uuid128, sizeof(ble_base_uuid)) == 0; + } else { + return false; } - - return ble_uuid_cmp(&m_uuid.u, &rhs.m_uuid.u) == 0; } - return m_valueSet == rhs.m_valueSet; -} + if (this->bitSize() != BLE_UUID_TYPE_128) { + return this->getValue() == rhs.getValue(); + } + return memcmp(this->getValue(), rhs.getValue(), 16); +} // operator== /** * @brief Convenience operator to check if this UUID is not equal to another. */ -bool NimBLEUUID::operator !=(const NimBLEUUID & rhs) const { +bool NimBLEUUID::operator!=(const NimBLEUUID& rhs) const { return !this->operator==(rhs); -} - +} // operator!= /** * @brief Convenience operator to convert this UUID to string representation. @@ -349,12 +307,8 @@ bool NimBLEUUID::operator !=(const NimBLEUUID & rhs) const { * that accept std::string and/or or it's methods as a parameter. */ NimBLEUUID::operator std::string() const { - if (!m_valueSet) return std::string(); // If we have no value, nothing to format. - char buf[BLE_UUID_STR_LEN]; - return ble_uuid_to_str(&m_uuid.u, buf); -} - +} // operator std::string #endif /* CONFIG_BT_ENABLED */ diff --git a/src/NimBLEUUID.h b/src/NimBLEUUID.h index 2c24971..18d933e 100644 --- a/src/NimBLEUUID.h +++ b/src/NimBLEUUID.h @@ -12,53 +12,59 @@ * Author: kolban */ -#ifndef COMPONENTS_NIMBLEUUID_H_ -#define COMPONENTS_NIMBLEUUID_H_ +#ifndef NIMBLE_CPP_UUID_H_ +#define NIMBLE_CPP_UUID_H_ #include "nimconfig.h" #if defined(CONFIG_BT_ENABLED) -#if defined(CONFIG_NIMBLE_CPP_IDF) -#include "host/ble_uuid.h" -#else -#include "nimble/nimble/host/include/host/ble_uuid.h" -#endif +# if defined(CONFIG_NIMBLE_CPP_IDF) +# include "host/ble_uuid.h" +# else +# include "nimble/nimble/host/include/host/ble_uuid.h" +# endif /**** FIX COMPILATION ****/ -#undef min -#undef max +# undef min +# undef max /**************************/ -#include +# include +# include /** * @brief A model of a %BLE UUID. */ class NimBLEUUID { -public: - NimBLEUUID(const std::string &uuid); + public: + /** + * @brief Created a blank UUID. + */ + NimBLEUUID() = default; + NimBLEUUID(const std::string& uuid); NimBLEUUID(uint16_t uuid); NimBLEUUID(uint32_t uuid); NimBLEUUID(const ble_uuid128_t* uuid); - NimBLEUUID(const uint8_t* pData, size_t size, bool msbFirst); + NimBLEUUID(const uint8_t* pData, size_t size); NimBLEUUID(uint32_t first, uint16_t second, uint16_t third, uint64_t fourth); - NimBLEUUID(); - uint8_t bitSize() const; - bool equals(const NimBLEUUID &uuid) const; - const ble_uuid_any_t* getNative() const; - const NimBLEUUID & to128(); - const NimBLEUUID& to16(); - std::string toString() const; - static NimBLEUUID fromString(const std::string &uuid); + uint8_t bitSize() const; + const uint8_t* getValue() const; + const ble_uuid_t* getBase() const; + bool equals(const NimBLEUUID& uuid) const; + std::string toString() const; + static NimBLEUUID fromString(const std::string& uuid); + const NimBLEUUID& to128(); + const NimBLEUUID& to16(); + const NimBLEUUID& reverseByteOrder(); - bool operator ==(const NimBLEUUID & rhs) const; - bool operator !=(const NimBLEUUID & rhs) const; - operator std::string() const; + bool operator==(const NimBLEUUID& rhs) const; + bool operator!=(const NimBLEUUID& rhs) const; + operator std::string() const; -private: - ble_uuid_any_t m_uuid; - bool m_valueSet = false; + private: + ble_uuid_any_t m_uuid{}; }; // NimBLEUUID + #endif /* CONFIG_BT_ENABLED */ -#endif /* COMPONENTS_NIMBLEUUID_H_ */ +#endif /* NIMBLE_CPP_UUID_H_ */