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
> 

Reply via email to