This is an automated email from the ASF dual-hosted git repository. janc pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git
commit 5812f7d9824554eedaf49ebcc16f3618dcd24ac0 Author: Jakub Rotkiewicz <[email protected]> AuthorDate: Fri Jul 28 16:10:17 2023 +0200 host: Added function to parse UUID from string --- nimble/host/include/host/ble_uuid.h | 19 +++++ nimble/host/src/ble_uuid.c | 150 ++++++++++++++++++++++++++++++++++++ 2 files changed, 169 insertions(+) diff --git a/nimble/host/include/host/ble_uuid.h b/nimble/host/include/host/ble_uuid.h index a63104b4..be96bb42 100644 --- a/nimble/host/include/host/ble_uuid.h +++ b/nimble/host/include/host/ble_uuid.h @@ -253,6 +253,25 @@ void ble_uuid_copy(ble_uuid_any_t *dst, const ble_uuid_t *src); */ char *ble_uuid_to_str(const ble_uuid_t *uuid, char *dst); +/** + * @brief Converts the specified UUID string to ble_uuid_any_t representation. + * If the UUID is recognised as Bluetooth SIG UUID, it will provide its + * 32-bit or 16-bit representation. + * + * Example 128-bit string representations: + * o "12345678-1234-1234-1234-123456789abc" + * o "12345678123412341234123456789abc" + * + * @param uuid Destination UUID. + * @param str The source string UUID. + * + * @return 0 on success, + * BLE_HS_EINVAL if the specified UUID string has wrong size or + * contains disallowed characters. + */ +int +ble_uuid_from_str(ble_uuid_any_t *uuid, const char *str); + /** @brief Converts the specified 16-bit UUID to a uint16_t. * * @param uuid The source UUID to convert. diff --git a/nimble/host/src/ble_uuid.c b/nimble/host/src/ble_uuid.c index acf016a1..afc437b7 100644 --- a/nimble/host/src/ble_uuid.c +++ b/nimble/host/src/ble_uuid.c @@ -26,6 +26,10 @@ #include "ble_hs_priv.h" #include "host/ble_uuid.h" +#define BLE_UUID16_STR_MAX_LEN 6 +#define BLE_UUID32_STR_MAX_LEN 10 +#define BLE_UUID128_STR_MAX_LEN 36 + static uint8_t ble_uuid_base[16] = { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 @@ -40,6 +44,52 @@ static uint8_t ble_uuid_base[16] = { #define VERIFY_UUID(uuid) #endif +static int +hex2val(char c, uint8_t *value) +{ + if (c >= '0' && c <= '9') { + *value = c - '0'; + } else if (c >= 'a' && c <= 'f') { + *value = c - 'a' + 10; + } else if (c >= 'A' && c <= 'F') { + *value = c - 'A' + 10; + } else { + return BLE_HS_EINVAL; + } + return 0; +} + + +static size_t +hex2bin(const char *hex, uint8_t *bin, size_t bin_len) +{ + size_t len = 0; + uint8_t tmp_val; + int rc; + + while (*hex && len < bin_len) { + rc = hex2val(*hex++, &tmp_val); + if (rc < 0) { + return 0; + } + + bin[len] = tmp_val << 4; + + if (!*hex) { + len++; + break; + } + + rc = hex2val(*hex++, &tmp_val); + if (rc < 0) { + return 0; + } + bin[len++] |= tmp_val; + } + + return len; +} + int ble_uuid_init_from_buf(ble_uuid_any_t *uuid, const void *buf, size_t len) { @@ -136,6 +186,106 @@ ble_uuid_to_str(const ble_uuid_t *uuid, char *dst) return dst; } +int +ble_uuid_from_str(ble_uuid_any_t *uuid, const char *str) +{ + uint8_t tmp_rslt = 0; + uint8_t *u8p; + const char *str_ptr; + uint16_t u16 = 0; + uint32_t u32 = 0; + int len = (int) strlen(str); + + if ((len < 4) || (len % 2 != 0)) { + return BLE_HS_EINVAL; + } + + str_ptr = &str[len - 2]; + + if (len <= BLE_UUID16_STR_MAX_LEN) { + uuid->u.type = BLE_UUID_TYPE_16; + } else if (len <= BLE_UUID32_STR_MAX_LEN) { + uuid->u.type = BLE_UUID_TYPE_32; + } else if (len <= BLE_UUID128_STR_MAX_LEN) { + uuid->u.type = BLE_UUID_TYPE_128; + } else { + return BLE_HS_EINVAL; + } + + switch (uuid->u.type) { + case BLE_UUID_TYPE_128: + uuid->u.type = BLE_UUID_TYPE_128; + u8p = uuid->u128.value; + for (int i = 0; i < 16; i++) { + if (hex2bin(str_ptr, u8p, 1) != 1) { + return BLE_HS_EINVAL; + } + + /* Check if string end */ + if (str_ptr == str) { + break; + } + + /* Remove '-' */ + if (*(str_ptr - 1) == '-') { + str_ptr--; + } + + str_ptr -= 2; + u8p++; + } + + if (memcmp(ble_uuid_base, uuid->u128.value, 12) == 0) { + uint8_t *tmp_ptr = &uuid->u128.value[12]; + uint32_t tmp_val32 = 0; + for (int i = 0; i < 4; i++) { + tmp_val32 |= ((uint32_t)(*tmp_ptr++) << 8 * i); + } + + if (tmp_val32 <= UINT16_MAX) { + uuid->u.type = BLE_UUID_TYPE_16; + uuid->u16.value = (uint16_t) tmp_val32; + } else { + uuid->u.type = BLE_UUID_TYPE_32; + uuid->u32.value = tmp_val32; + } + } + break; + case BLE_UUID_TYPE_32: + for (int i = 0; i < 4; i++) { + if (hex2bin(str_ptr, &tmp_rslt, 1) != 1) { + return BLE_HS_EINVAL; + } + u32 |= ((uint32_t) tmp_rslt) << (i * 8); + + if (str_ptr == str) { + break; + } + str_ptr -= 2; + } + uuid->u32.value = u32; + break; + case BLE_UUID_TYPE_16: + for (int i = 0; i < 2; i++) { + if (hex2bin(str_ptr, &tmp_rslt, 1) != 1) { + return BLE_HS_EINVAL; + } + u16 |= ((uint32_t) tmp_rslt) << (i * 8); + + if (str_ptr == str) { + break; + } + str_ptr -= 2; + } + uuid->u16.value = u16; + break; + default: + return BLE_HS_EINVAL; + } + + return 0; +} + uint16_t ble_uuid_u16(const ble_uuid_t *uuid) {
