5. The Bluetooth® Device Address
Bluetooth® devices identify themselves using a 48-bit device address. This is commonly represented as a set of 12-hex digits and is often referred to as a BD address. These addresses are used in order to manage connections and keep track of BLE bondings.
Figure 12 12-hex digits as Bluetooth device address
iOS address hex
If you are using a Bluetooth® Explorer Tool on an iOS device then the BD address will not be displayed. If you don’t have access to an Android phone then try using the Bluetooth® Explorer Tool built into the Chrome browser, see Before You Get Started for details.
- There are two types of BD addresses:
- Public addresses:
They are registered with and purchased from the IEEE and contain an identifier of the entity who registered the address range (OUI). Public addresses remain static and unique for a given Bluetooth® device.
- Non-public addresses:
No registration with the IEEE is required (and no payments to be made)
The first two bits of a non-public address are binary ones. In other words, the first hex digit of the address must be
0xC
,0xD
,0xE
, or0xF
The address can be device specific and remain constant over the life of a product
The address can change at some given interval - often to ensure some level of privacy
The address can be randomly generated at boot-up
Random addresses
Non-public addresses are often inaccurately labeled as Random. This term is misleading because, although these addresses can be generated randomly, they don’t have to be truly random.
- SDK6 offers various methods for the assignment of the Bluetooth® Device Address:
- If you are using a public address
A BD Address can be stored in a specific part of the OTP of the device during production. The SDK will automatically handle this. If you are using a module then this field has likely already been programmed
If there is no address stored in OTP, the SDK6 will assign the address provided in the file: …_config_advanced.h (previously mentioned these files in User configuration modules .The address is defined as
CFG_NVDS_TAG_BD_ADDRESS
modify this regarding target).
- If you are using a non-public address
The SDK6 can manage generation of a random address at boot-up
The SDK6 can manage generation of a static random address which is unique to the device
The user can generate an address based on a custom scheme
In the following, we will explore the use of non-public addresses.
5.1. Non-public (Static BD Address)
We have already seen the result of using a public address which is how empty_peripheral_template was implemented initially. In the following we will explore options for generation of non-public addresses. First, we will allow the SDK6 to set a new random non-public address at every boot-up.
- In user_config.h, change the definition of
USER_CFG_ADDRESS_MODE
toAPP_CFG_ADDR_STATIC
/************************************************************************* * Privacy Capabilities and address configuration of local device: * - APP_CFG_ADDR_PUB No Privacy, Public BDA * - APP_CFG_ADDR_STATIC No Privacy, Random Static BDA * - APP_CFG_HOST_PRIV_RPA Host Privacy, RPA, Public Identity * - APP_CFG_HOST_PRIV_NRPA Host Privacy, NRPA (non-connectable ONLY) * - APP_CFG_CNTL_PRIV_RPA_PUB Controller Privacy, RPA or PUB, Public Identity * - APP_CFG_CNTL_PRIV_RPA_RAND Controller Privacy, RPA, Public Identity * * Select only one option for privacy / addressing configuration. ************************************************************************** */ #define USER_CFG_ADDRESS_MODE APP_CFG_ADDR_STATIC
- In user_config.h, change the definition of
Build the project (F7) and load it onto target (twice, press Ctrl+F5)
Use your BLE explorer app to verify that the BD address has changed and that it changes at every reboot.
5.2. Non-public (Static Unique BD Address)
In software development and certain applications, having a static and unique address for a device is often crucial. This would be an address that does not change after a reboot and that is globally unique to a specific device.
- We can achieve this with a minor modification of the callback triggered when a non-public address is requested by the BLE stack:
Open the file user_callback_config.h and identify the callback
app_on_generate_static_random_addr
. This callback is currently re-routed to the functiondefault_app_generate_static_random_addr
- Change the re-routing to the function
default_app_generate_unique_static_random_addr
: - .app_on_generate_static_random_addr = default_app_generate_static_random_addr, + .app_on_generate_static_random_addr = default_app_generate_unique_static_random_addr,
- Change the re-routing to the function
Build the project (F7) and load it onto target (twice, press Ctrl+F5)
Use your BLE explorer app to verify that the BD address has changed and that it no longer changes at every reboot. If you have a second development kit, you will be able to observe that it advertises it’s own static unique address when running the same firmware
5.3. Non-public (User Generated BDAddress)
Occasionally, the user would like to assign a BD address based on some custom scheme. To handle this we will need to again re-route the callback that we just modified - this time to our own custom function.
- This bonus re-routing will also show you how to redirect a callback to user space, a basic concept in SDK6:
Open the file user_callback_config.h and identify the callback
app_on_generate_static_random_addr
.- Re-route the callback to a, still to be implemented, custom function that we will call
user_get_bdaddr
: - .app_on_generate_static_random_addr = app_on_generate_static_random_addr, + .app_on_generate_static_random_addr = user_get_bdaddr,
- Re-route the callback to a, still to be implemented, custom function that we will call
- In empty_peripheral_template.h, add a prototype for the custom function we are about to implement:
void user_get_bdaddr( struct bd_addr* address );
- We are now ready to implement the user generated BD address assignment. At the bottom of the user_empty_peripheral_template.c file, add the following function:
void user_get_bdaddr( struct bd_addr *address ) { struct bd_addr tempAddr = {0xEE,0xFF,0xC0,0xEE,0xFF,0xC0}; memcpy(address, &tempAddr, 6); }
Build the project (F7) and load it onto target (twice, press Ctrl+F5)
Use your BLE explorer app to verify that the BD address has changed to C0:FF:EE:C0:FF:EE (notice that we provided the address in little-endian format).
Hint
Some explanation is required as this point. The callback sends us a pointer to a structure that our function can populate with a new BD address.We basically copy our custom address into this structure of 6 octets using memcpy
.