|  | /* | 
|  | * Copyright (c) 2017 Nordic Semiconductor ASA | 
|  | * Copyright (c) 2015 Intel Corporation | 
|  | * | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  |  | 
|  | #include <errno.h> | 
|  | #include <stdbool.h> | 
|  | #include <string.h> | 
|  |  | 
|  | #include <zephyr/bluetooth/addr.h> | 
|  | #include <zephyr/bluetooth/crypto.h> | 
|  | #include <zephyr/sys/util.h> | 
|  |  | 
|  | #define ADDR_RESOLVED_BITMASK (0x02) | 
|  |  | 
|  | static inline int create_random_addr(bt_addr_le_t *addr) | 
|  | { | 
|  | addr->type = BT_ADDR_LE_RANDOM; | 
|  |  | 
|  | return bt_rand(addr->a.val, 6); | 
|  | } | 
|  |  | 
|  | int bt_addr_le_create_nrpa(bt_addr_le_t *addr) | 
|  | { | 
|  | int err; | 
|  |  | 
|  | err = create_random_addr(addr); | 
|  | if (err) { | 
|  | return err; | 
|  | } | 
|  |  | 
|  | BT_ADDR_SET_NRPA(&addr->a); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int bt_addr_le_create_static(bt_addr_le_t *addr) | 
|  | { | 
|  | int err; | 
|  |  | 
|  | err = create_random_addr(addr); | 
|  | if (err) { | 
|  | return err; | 
|  | } | 
|  |  | 
|  | BT_ADDR_SET_STATIC(&addr->a); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int bt_addr_from_str(const char *str, bt_addr_t *addr) | 
|  | { | 
|  | /* Parse a null-terminated string with a Bluetooth address in | 
|  | * canonical "XX:XX:XX:XX:XX:XX" format. | 
|  | */ | 
|  |  | 
|  | const size_t len = strlen(str); | 
|  |  | 
|  | /* Verify length. */ | 
|  | if (len != BT_ADDR_STR_LEN - 1) { | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | /* Verify that all the colons are present. */ | 
|  | for (size_t i = 2; i < len; i += 3) { | 
|  | if (str[i] != ':') { | 
|  | return -EINVAL; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Parse each octet as hex and populate `addr->val`. It must be | 
|  | * reversed since `bt_addr_t` is in 'on-air' format. | 
|  | */ | 
|  | for (size_t i = 0; i < ARRAY_SIZE(addr->val); i++) { | 
|  | const size_t reverse_i = ARRAY_SIZE(addr->val) - 1 - i; | 
|  |  | 
|  | if (!hex2bin(&str[i * 3], 2, &addr->val[reverse_i], 1)) { | 
|  | return -EINVAL; | 
|  | } | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int bt_addr_le_from_str(const char *str, const char *type, bt_addr_le_t *addr) | 
|  | { | 
|  | int err; | 
|  |  | 
|  | err = bt_addr_from_str(str, &addr->a); | 
|  | if (err < 0) { | 
|  | return err; | 
|  | } | 
|  |  | 
|  | if (!strcmp(type, "public") || !strcmp(type, "(public)")) { | 
|  | addr->type = BT_ADDR_LE_PUBLIC; | 
|  | } else if (!strcmp(type, "random") || !strcmp(type, "(random)")) { | 
|  | addr->type = BT_ADDR_LE_RANDOM; | 
|  | } else if (!strcmp(type, "public-id") || !strcmp(type, "(public-id)")) { | 
|  | addr->type = BT_ADDR_LE_PUBLIC_ID; | 
|  | } else if (!strcmp(type, "random-id") || !strcmp(type, "(random-id)")) { | 
|  | addr->type = BT_ADDR_LE_RANDOM_ID; | 
|  | } else { | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | void bt_addr_le_copy_resolved(bt_addr_le_t *dst, const bt_addr_le_t *src) | 
|  | { | 
|  | bt_addr_le_copy(dst, src); | 
|  | /* translate to "regular" address type */ | 
|  | dst->type &= ~ADDR_RESOLVED_BITMASK; | 
|  | } | 
|  |  | 
|  | bool bt_addr_le_is_resolved(const bt_addr_le_t *addr) | 
|  | { | 
|  | return (addr->type & ADDR_RESOLVED_BITMASK) != 0; | 
|  | } |