This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2640R2F-Q1: How to resolve peer device PRA using privacy 1.2 feature running Central Role?

Part Number: CC2640R2F-Q1
Other Parts Discussed in Thread: CC2640R2F, BLE-STACK

Hi,

We are running CC2640R2F device as Central. We would like to implement an application where CC2640R2F works as Central and phone acts as peripheral.

The phone will be advertising with specific UUID known to Central. Central filters the adv data and initiates a connection followed by BLE bonding.

Once both devices are bonded, Central should connect back to the bonded device using device BD address. Device BD addresses part of advertisement data will be PRA (Private Resolvable Address).

We are using simplelink_cc2640r2_sdk_1_40_00_45 (BLE 4.2 stack) in which Privacy 1.2 feature is enabled by default.

Here are the questions.

1. How can the central device resolve a bonded device PRA?

2. Can the centrtal device automatically connect to a bonded device? If yes, does the application get any notification?

3. Is there any API available which gets the bonded device public address if PRA is given as input?

Also, we can't restrict advertisements only from bonded devices as we need to connect new phones which can advertise a specific UUID besides bonded devices.

Regards,

Ravi,

  • Hi Ravi,

    1. Since you are using BLE-Stack v3.1.0, Controller-based privacy is used by default. When the devices bond, they share their IRKs with each other so that they can resolve the Resolvable Private Address that the device is using to an Identity Address. gapbondmgr.c contains the code for bonding. In gapBondMgrAddBond, you will see that the identity information for the peer device is passed to the Controller using HCI_LE_AddDeviceToResolvingListCmd. This allows that Controller to resolve device addresses before they get to the Host. If the Controller can resolve the device address (has valid peer identity information in the Resolving List), it will use the address type ADDRTYPE_PUBLIC_ID (0x03) when sending information about the peer device to the Host.

    2. Yes. The Simple Central Bidirectional Audio example has an example showing how to automatically connect to a peer based on advertising data: https://github.com/ti-simplelink/ble_examples/blob/master/examples/rtos/CC2640R2_LAUNCHXL/bleapps/simple_central_bidirectional_audio/readme.md

    The corresponding event is GAP_LINK_ESTABLISHED.

    3. Currently, we do not have an API that will provide a public address from an RPA. Can you explain your use case? How are you getting the peer's RPA? You will already have the identity address at the application level if you have exchanged IRKs.

  • Hi Rachel,

    Thank you for the response. Below are the responses/follow up questions.

    1. Can you confirm that  ADDRTYPE_PUBLIC_ID will be received only from the Bonded device (Which Controller know about the IRK) advertisements? In case of non bonded BLE devices (TV's and Tiles), ADDRTYPE_PUBLIC or ADDRTYPE_RANDOM    should be received.

    #define ADDRTYPE_PUBLIC 0x00 //!< Public Device Address
    #define ADDRTYPE_RANDOM 0x01 //!< Random Device Address
    #define ADDRTYPE_PUBLIC_ID 0x02 //!< Public Identity Address (corresponds to peer's RPA)
    #define ADDRTYPE_RANDOM_ID 0x03 //!< Random (static) Identity Address (corresponds to peer's RPA)

    2. I looked into the example project. In the example project, DEFAULT_BONDING_MODE is set to FALSE which means the IRKs will not be stored into NVM after pairing process. This may not the example suitable for our application.

    3. Let me explain our case in detail. We are developing a Central Module which will be listening to the advertisements from nearby BLE devices. We need to speak with certain phones which can advertise a Custom UUID. We have two ways of establishing a connection with Phone.

    a. Before Bonding

    -----------------------------------------

    1. The phone should advertise with a UUID which is known to Central.

    2. Cental will filter the adv data based on UUID and establishes connection

    3. After establishing the connection, it initiates BLE Pairing process with BONDING enabled.

    4. By end of Pairing, all the IRKs of Peer Device will be stored into NVM.

    b. After Bonding

    ---------------------------------------

    1. We have a requirement of connecting to multiple phones. At a time, we can connect upto 4 phones.

    2. We need to now identify devices which are already bonded as well as advertise a known UUID mentioned in step a.

    3. Phone 1 which is bonded in step1 will not send advertisements with known UUID as it is already bonded. But, central should be able to identify this device based on its bonded data stored in step a.

    4. We still need to connect Phone 2 which advertises a known UUID.

    5. This process should continue till we connect to MAXIMUM devices which will be 4.

  • Hello Rachel,

    Ravi also did the following test but did not see the code get to this section he was monitoring. 

    Should he be monitoring a different event?

    I tested our implementation by monitoring for ADDRTYPE_PUBLIC_ID  as address type as part if GAP_DEVICE_INFO_EVENT. But, we don't see any scan response posted from controller woith the above address type.
    Does the controller resolve the BD address part of scan response data from bonded devices automatically or Do we need to enable any settings?
    Please confirm.

        case GAP_DEVICE_INFO_EVENT:
          {

                /* Set up the container for the Device Info to be used in the Connection Manager. */
                DEVICE_INFO_EVENT_TYPE st_t_dev_info_evt;

                st_t_dev_info_evt.addressBytes = pEvent->deviceInfo.addr;
                st_t_dev_info_evt.addressType  = pEvent->deviceInfo.addrType;
                st_t_dev_info_evt.advDataLen   = pEvent->deviceInfo.dataLen;
                st_t_dev_info_evt.advData      = pEvent->deviceInfo.pEvtData;
                st_t_dev_info_evt.rssi         = pEvent->deviceInfo.rssi;
                /* Only Check Advert Data if the address type is PRA */
                if(st_t_dev_info_evt.addressType == ADDRTYPE_RANDOM)
                {
                    /* Notify the Connection Manager of the Device Info we just received in this event. */
                    vd_g_ConnectionMgr_OnDeviceInfo(&st_t_dev_info_evt);
                }
                else if(st_t_dev_info_evt.addressType == ADDRTYPE_PUBLIC_ID)
                {
                    /* We found a Bonded Device */
                    vd_g_ConnectionMgr_OnBondedDeviceInfo(&st_t_dev_info_evt);
                }

    Essentially, they want the central device (application) to know whether the device being scanned is already a bonded device or not. 

    Does the controller auto-connect to the previously bonded device? They can store a lot of bonded devices, but need application level access to initiate a connection. How can this be accomplished?

  • Hi Ravi,

    Thanks for clarifying the use case. Here are my responses to your follow up questions:

    1. I can confirm that if your peer device is advertising with a Resolvable Private Address and the Controller resolves it (after bonding), it will pass the information to the Host with ADDRTYPE_PUBLIC_ID. However, there is one caveat: If your device is advertising with a Public Address, the Controller will not try to resolve it so, even if you are bonded, you will receive a ADDRTYPE_PUBLIC at the Host or App level. The Public ID type tells you if the address was resolved.

    2. The example was just to show an example of automatically connecting to a known peer device. You can enable bonding if you want by setting the flag to TRUE, but that particular example doesn't require it.

    3. If you are sure that all of your Peer Devices are using RPAs then checking address type would be a good test for if you are bonded or not. If you are connecting to some devices that may be using a Public Address, you will need another approach. If that is the case, please let me know so I can find the best way to solve this problem.
  • Hi Prasanna,

    I'm not sure that I understand your test correctly. Does this summary sound correct?

    1. Scan for devices
    2. Find a device with the UUID in question
    3. Connect, pair, bond, disconnect
    4. Scan for devices
    5. Check scan results for address type

    The controller should resolve any bonded device addresses. If it's not, please let me know how I can reproduce starting from an example app for the LaunchPad. Are you using Simple Central as a starting point? You have verified the peer device is still advertising after the disconnection?

    To see an example of auto connecting, refer to the audio example I mentioned previously. It does not show auto connecting to bonded devices. If you are removing the UUID from the advertising data after a bond is stored, you can check the address type. If you get Public ID, you can assume you have bonded to the device and issue a GAP Establish Link Request with the peer's address from the Device Info Event.
  • Hi Rachel,

    3. If you are sure that all of your Peer Devices are using RPAs then checking address type would be a good test for if you are bonded or not. If you are connecting to some devices that may be using a Public Address, you will need another approach. If that is the case, please let me know so I can find the best way to solve this problem.

    At this point , I am not sure that Peer Devices are using RPA once they are bonded. Can you also let me know the process to reolve if peer device uses public address.

    I did some more debugging into gapbondmgr.c file where I stepped into gapBondMgrAddBond function.

    HCI_LE_AddDeviceToResolvingListCmd will be executed only if gapState == GAP_STATE_IDLE.

    But, none of the time it is executing the above function and it is entering into else condition.

    Why the check is required and who sets the variable to GAP_STATE_IDLE?
    // Add device to resolving list
    if ( gapState == GAP_STATE_IDLE )
    {
    HCI_LE_AddDeviceToResolvingListCmd( ( pPkt->pIdentityInfo->addrType &
    MASK_ADDRTYPE_ID ),
    pPkt->pIdentityInfo->bd_addr,
    pPkt->pIdentityInfo->irk,
    NULL );
    }
    else
    {
    // Controller must be in adv/scan/init state, so set syncRL flag
    // and wait for idle period to sync the bond records and RL
    gapBond_syncRL = TRUE;
    }
  • Hi Rachel,

    Do we need to call HCI_LE_SetAddressResolutionEnableCmd explicitly to make the controller resolve private resolvable addresses? Please comment on this.
  • Hi Ravi,

    I think this may be easier to demonstrate if I modify the Simple Central example to show the address type. Please allow me some time to make my changes. I will post the modified code files here when they are ready.
  • Hi Ravi,

    I am attaching a modified version of simple_central.c at the bottom of this post that will display the address type for peer devices you wish to connect to. Here is how I would recommend you use this. This test requires 2 LaunchPads and a terminal window for each device to display the output.

    1. Use the modified Simple Central to discover and connect to a LaunchPad running a default Simple Peripheral project. You will see Address Type 0 before and after bonding.

    2. Modify Simple Peripheral to use an RPA by adding the following code to peripheral.c in gapRole_processGAPMsg after gapRole_state = GAPROLE_STARTED;

    //set address type to resolvable private address
    stat = GAP_ConfigDeviceAddr(ADDRMODE_PRIVATE_RESOLVE, NULL);
    
    if (stat != SUCCESS)
    {
        System_abort("Error!");
    }
    
    //Set timeout value to 5 minute
    GAP_SetParamValue( TGAP_PRIVATE_ADDR_INT , 5);

    3. Use modified Simple Central to discover modified Simple Peripheral. You will now see the device advertising with Address Type 1 before bonding.

    4. Connect to modified Simple Peripheral and allow bonding to occur. Disconnect the devices and rediscover. You will now see the Address Type is 2 and you can match the Device Address displayed in the Simple Central discovery results with the address displayed at the top of the Simple Peripheral terminal window.

    Please let me know if you have any trouble running this test.

    /cfs-file/__key/communityserver-discussions-components-files/538/1641.simple_5F00_central.c

  • Hi Rachel,

    Bonding_Issue_CentralPlusBroadcaster.doc

    I understood the controller is capable of resolving peer device address. But, the problem is the controller is unable to store the peer device IRK info as part of gapBondMgrAddBond function.

    Please find the document attached which explains our project setup and the issue in detail. Please let us know if you require more info.

  • Hi Rachel,

    Even though the thread started with unable to resolve address, I think we are facing different issues than the earlier.

    1. The Original issue of resolving the peer's address after bionding is working.

    But, with the below side effects.

    1. Some times, after Pairing, Radio Stops scanning.

    2. Once after restarting the radio, it starts scanning and can connect to the previous bonded device.

    3. Now, when we call GATT_DiscPrimaryServiceByUUID() returns INVALIDPARAMETER (0x02) all the time.

    4. As part of our previous project, we see some issue while storing gapBondCharCfg_t charCfg[GAP_CHAR_CFG_MAX]; into NVM and one of your engineer provided a version where charcfg are no longer maintained in NVM. Reason is our project doesn't need them.
    Does it causes any of the issues listed above?
  • Hi Ravi,

    I reviewed the document you sent. Things do become a little complicated if you are doing a multirole application. The Resolving List cannot be modified while you are in a scanning, initiating, or advertising state. However, the bond manager should still store the peer device IRK info into NV memory as part of the bonding process. Then, when the gapstate is idle, GAP Bond Manager will call GAPBondMgr_syncResolvingList which will take care of getting the information from the bond data to the controller.

    You should still be able to resolve a peer address, even if it isn't added to the resolving list right away. Please let me know if you see further issues with address resolution.

    As far as your other issues, I do not think they would be caused by removing the char cfg storage. If you are having trouble with scanning during a connection, it is more likely that your scan events are conflicting with connection events. The controller will prioritize connections. To see if this could be the issue, try changing your scan duration to be longer than your connection interval. You should see better results because the scan can occur after the connection event ends.