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, or0xFThe 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_ADDRESSmodify 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_MODEtoAPP_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.