Marcel: Thanks for the clarification on the public address and that for BLE the two LSbits of the MSbyte do not apply. I do understand the trickiness of changing the public address but it is certainly helpful for debugging/testing.
> On Apr 3, 2017, at 9:38 AM, Marcel Holtmann <[email protected]> wrote: > > 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 >
