Hi Will, >>> There has been some discussion of this already on the list but nothing has >>> been done yet so I wanted to resurrect the conversation with some proposals. >>> >>> What we are trying to do here is the following: >>> 1) Have the controller get a public device address without it being >>> hardcoded. >>> 2) Have the ability to read a chip-specific random static address if the >>> chip has one programmed. >>> >>> The proposal is the following: >>> >>> 1) Add two new API. These will be platform specific and will be placed in >>> the ble_hw.c file: >>> >>> /* These API will return -1 if no address available. If available, will >>> return 0 and will place the address in *addr */ >>> int ble_hw_get_public_addr(ble_addr_t *addr) >>> int ble_hw_get_static_addr(ble_addr_t *addr) >>> >>> 2) Add a syscfg variable to the controller which will allow the developer >>> to set a public address of their choosing. By default this will be all 0 >>> (no public address). More on this below. >>> >>> 3) The ble_hw_get_public_addr function will do the following: >>> * If the user has overridden the default public address (the syscfg >>> variable) with a non-zero public address, that address will be returned by >>> this function. >>> * If the default public address in the syscfg is all zero, the code will >>> read FICR and check if the device address type in the FICR is public. If >>> so, it means the nordic chip was factory programmed with a public address >>> and this will be used. >>> * If both of the above checks fail, the code will read UICR[0] and UICR[1] >>> to see if a public address has been programmed into the UICR. We are doing >>> this to make it easy for folks to program their development kits with >>> public addresses so they do not have to hardcode them. UICR[0] will contain >>> the least significant 4 bytes of the device address. UICR[1] will contain >>> the most significant two bytes. The upper 16 bits of this word should be >>> set to 0. The API will presume that this is a valid public device address >>> as long as the upper 16-bits of this 32-bit word are all zero. We will also >>> check to see if this is a valid public address (see below). If both UICR[0] >>> and UICR[1] are zero, this will not be considered a valid public address. >>> >>> A note on valid public addresses. Not sure if I got this right, but I think >>> the two least significant bits of the most significant byte of the public >>> address should be zero. I think I will check this to make sure it is valid. >> >> you got that wrong. The public address is a BD_ADDR (6 octets) and the >> random address is that (also 6 octets). If you just get 6 octets, you can >> not differentiate if it is public or random. That is why I keep that LE >> addresses are actually 49 bits instead. There is "out-of-band” telling if >> its public or random. >> > The above comment is not based on the BLE specification, it is based on the > IEEE standard which says that the two LSbit’s of the MSbyte are the > universally/locally administered addres bit and the indiviual/group address > bit. I was presuming that both of these bits need to be zero but was not > sure. I was only referring to public addresses here.
the BD_ADDR usage and its relation to IEEE is defined in the standard. The bits and its assignment are irrelevant since it is treated as 6 octets (defined as 3 parts). But that is for BR/EDR only. For LE it is just a 6 octet value marked as public address. >> As far I know the FICR is just a 6 octet random value. It is neither a >> public address or a static random address (you are after the static after >> all since NRPAs and RPAs are different as well). So you even need to mask >> the upper 2 bits correctly to make FICR a static address. > > Marcel: you are incorrect I Ibelieve. I should have been more specific. There > is a DEVICEADDRTYPE register in the FICR which says whether the address is > public or random. The code was going to read that register to determine if > the address in the FICR was public or random. I do not expect that register > being set to public but if it is, the adress in the next two FICR registers > should be the public address. Good to know. If that is set to public address, then HCI_Read_BD_ADDR should return that value. >> >>> 4) The ble_hw_get_static_addr() will do the following: >>> * Read the FICR to see if there is a random address in the FICR. This is >>> the default programming of the nrf51dk and nrf52dk. Unless you have them >>> program a public device address in the FICR, it will have a random address. >>> * If the chip does not have a random address the API returns -1. >> >> See my comment above, the FICR is just 6 octets random data. It is surely >> not a public address. It can never be since that requires to follow IEEE >> assignment rules. And it is no static address either. It needs to be masked >> correctly first. It is just a persistence 6 octets of randomness from >> manufacturing. > I know it is not a public address! Well, it is not a public address if the > DEVICEADDRTYPE says it is not. I was merely trying to point out the > possibility that there is not a random address here. And yes, I have read the > nordic devzone and I know I need to set the upper two bits accordingly. I > skipped that because I already know this and would not have a returned the > address with those bits not being set. I even posted on the nordic devzone to > get clarification on this. But I should have mentioned it here. >> >>> Some things about writing apps and the BLE spec: >>> 1) I realize that it is the host that tells the controller the random >>> address to use. The controller will NOT automatically use the random >>> address from ble_hw_get_static_addr(). That API will be added as a >>> convenience so that the app developer does not have to generate their own. >>> If the app wants to use this random address it needs to tell the controller >>> to use it using LE_Set_Random_Addr. >>> >>> 2) Regarding the public device address. We have an app called bletiny that >>> can set the public device address I think. If the above gets approved we >>> are going to remove g_dev_addr from the code; it will be kept in the >>> controller and not available globally. The Zephyr project is considering >>> adding vendor specific HCI commands, one of which is “set public device >>> address”. I think if we go with the above approach we should add this >>> vendor specific command and that should be the way an app can set the >>> public device address if it so chooses. >> >> The public BD_ADDR needs to be inside the controller before the call of >> HCI_Reset. Otherwise all sort of assumptions on HCI break. Until then the >> HCI_Read_BD_ADDR has to return 00:00:00:00:00:00 to indicate the controller >> has no public address. Switching the BD_ADDR mid-flight with a backdoor is >> going to fail in the most funny ways left and right. >> > Was I wrong about this? I thought that one of the vendor specific additions > was to set the public address? If not The Bluetooth Core spec does not have any provision for ever changing the BD_ADDR. However certain needs of NVM storage forced us to have the address in the host storage area instead of the controller. So changing the address is an option that almost any controller supports. However it comes with certain restrictions. That is why almost every manufacturer binds it actual active change to HCI_Reset happening. Changning it mid flight is dangerous. Regards Marcel
