Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions examples/NimBLE_Server/main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ extern "C" void app_main(void) {
pServer = NimBLEDevice::createServer();
pServer->setCallbacks(serverCallbacks);

NimBLEService* pDeadService = pServer->createService("DEAD");
NimBLEService* pDeadService = pServer->createService(0xDEAD);
NimBLECharacteristic* pBeefCharacteristic =
pDeadService->createCharacteristic("BEEF",
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE |
Expand All @@ -172,7 +172,7 @@ extern "C" void app_main(void) {
pBeef2904->setFormat(NimBLE2904::FORMAT_UTF8);
pBeef2904->setCallbacks(dscCallbacks);

NimBLEService* pBaadService = pServer->createService("BAAD");
NimBLEService* pBaadService = pServer->createService(0xBAAD);
NimBLECharacteristic* pFoodCharacteristic =
pBaadService->createCharacteristic("F00D", NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::NOTIFY);

Expand Down Expand Up @@ -204,7 +204,7 @@ extern "C" void app_main(void) {
/** Loop here and send notifications to connected peers */
for (;;) {
if (pServer->getConnectedCount()) {
NimBLEService* pSvc = pServer->getServiceByUUID("BAAD");
NimBLEService* pSvc = pServer->getServiceByUUID(0xBAAD);
if (pSvc) {
NimBLECharacteristic* pChr = pSvc->getCharacteristic("F00D");
if (pChr) {
Expand Down
144 changes: 85 additions & 59 deletions src/NimBLEUUID.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,29 +69,83 @@ NimBLEUUID::NimBLEUUID(const ble_uuid_t* uuid) {
*
* @param [in] value The string to build a UUID from.
*/
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(), 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);
NimBLEUUID::NimBLEUUID(const char* value) {
uint8_t* dest = nullptr;
size_t byteIdx = 0;
bool lowNibble = true;
size_t len = 0;

if (value == nullptr) {
goto error;
}

len = strlen(value);
if (len < 4) {
goto error;
}

if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X')) {
value += 2;
len -= 2;
}

// NimBLE stores UUIDs little endian, so write the bytes directly into the value field.
if (len == 4) {
m_uuid.u.type = BLE_UUID_TYPE_16;
dest = reinterpret_cast<uint8_t*>(&m_uuid.u16.value);
} else if (len == 8) {
m_uuid.u.type = BLE_UUID_TYPE_32;
dest = reinterpret_cast<uint8_t*>(&m_uuid.u32.value);
} else if (len == 36) {
m_uuid.u.type = BLE_UUID_TYPE_128;
dest = m_uuid.u128.value;
} else {
NIMBLE_LOGE(LOG_TAG, "Invalid UUID length");
m_uuid.u.type = 0;
goto error;
}

// Parse the string from the end so the least significant byte is stored first.
for (size_t i = len; i-- > 0;) {
// Ensure hyphens are in the correct positions for 36-character UUIDs.
if (len == 36 && (i == 8 || i == 13 || i == 18 || i == 23)) {
if (value[i] != '-') {
goto error;
}
continue;
}

uint8_t nibble = NimBLEUtils::hexToByte(value[i]);
if (nibble == 0xFF) {
goto error;
}

if (lowNibble) {
dest[byteIdx] = nibble;
} else {
dest[byteIdx++] |= nibble << 4;
}
lowNibble = !lowNibble;
}

return;

error:
m_uuid = ble_uuid_any_t{};
NIMBLE_LOGE(LOG_TAG, "Invalid UUID");
} // NimBLEUUID(const char*)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved

/**
* @brief Create a UUID from a std::string.
* @param [in] value The string to build a UUID from.
*/
NimBLEUUID::NimBLEUUID(const std::string& value) {
if (value.length() == 16) {
m_uuid.u.type = BLE_UUID_TYPE_128;
memcpy(m_uuid.u128.value, value.data(), 16);
return;
}
} // NimBLEUUID(std::string)

*this = NimBLEUUID(value.c_str());
} // NimBLEUUID(const std::string& value)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved

/**
* @brief Create a UUID from 2, 4, 16 bytes of memory.
Expand All @@ -106,22 +160,17 @@ NimBLEUUID::NimBLEUUID(const uint8_t* pData, size_t size) {
} // 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;
} // NimBLEUUID(uint16_t uuid)

/**
* @brief Create a UUID from the 32bit value.
* @param [in] uuid The 32bit short form UUID.
* @brief Create a UUID from an int value.
* @param [in] uuid The int short form UUID.
*/
NimBLEUUID::NimBLEUUID(uint32_t uuid) {
m_uuid.u.type = BLE_UUID_TYPE_32;
m_uuid.u32.value = uuid;
} // NimBLEUUID(uint32_t uuid)
m_uuid.u.type = (uuid > UINT16_MAX) ? BLE_UUID_TYPE_32 : BLE_UUID_TYPE_16;
if (m_uuid.u.type == BLE_UUID_TYPE_16) {
m_uuid.u16.value = static_cast<uint16_t>(uuid);
} else {
m_uuid.u32.value = static_cast<uint32_t>(uuid);
}
} // NimBLEUUID(int uuid)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved

/**
* @brief Create a UUID from the native UUID.
Expand Down Expand Up @@ -196,34 +245,11 @@ bool NimBLEUUID::equals(const NimBLEUUID& uuid) const {
} // equals

/**
* Create a NimBLEUUID from a string of the form:
* 0xNNNN
* 0xNNNNNNNN
* 0x<UUID\>
* NNNN
* NNNNNNNN
* <UUID\>
*
* Create a NimBLEUUID from a string.
* @param [in] uuid The string to create the UUID from.
*/
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) {
uint16_t x = strtoul(uuid.substr(start, len).c_str(), NULL, 16);
return NimBLEUUID(x);
} else if (len == 8) {
uint32_t x = strtoul(uuid.substr(start, len).c_str(), NULL, 16);
return NimBLEUUID(x);
} else if (len == 36) {
return NimBLEUUID(uuid);
}

return NimBLEUUID();
return NimBLEUUID(uuid.c_str());
} // fromString

/**
Expand Down
2 changes: 1 addition & 1 deletion src/NimBLEUUID.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ class NimBLEUUID {
NimBLEUUID() = default;
NimBLEUUID(const ble_uuid_any_t& uuid);
NimBLEUUID(const ble_uuid_t* uuid);
NimBLEUUID(const char* value);
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);
Expand Down
6 changes: 6 additions & 0 deletions src/NimBLEUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ class NimBLEUtils {
static NimBLEAddress generateAddr(bool nrpa);
static bool taskWait(const TaskData& taskData, uint32_t timeout);
static void taskRelease(const TaskData& taskData, int rc = 0);
static constexpr uint8_t hexToByte(char c) {
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
return 0xFF;
}

private:
friend class NimBLEDevice;
Expand Down
Loading