This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to resolve Initiator's address when direct advertising?

How to push Initiator to resolve its private address (seen at direct_addr of adv_report) when bonded private Advertiser does a direct advertising?

I need the only Initiator's own address to be resolved (based on device IRK) because I use software whitelisting for the reason of more than 8 peers so I don't call sd_ble_gap_whitelist_set() nether sd_ble_gap_device_identities_set(). As a consequence of no calls of these functions BLE_GAP_EVT_ADV_REPORT isn't fired when scan filter is BLE_GAP_SCAN_FP_ACCEPT_ALL. To receive adv reports filter should be changed to BLE_GAP_SCAN_FP_ALL_NOT_RESOLVED_DIRECTED but sd_ble_gap_connect() doesn't accept such setup.

I suppose the solution may be in pp_local_irks of sd_ble_gap_device_identities_set() but I can't get in mind how to use that based on description presented on Infocenter.

My case is most matched to variants #3 and #4 of Scan Private Devices MSC with the only difference: Advertiser's address shall remain unresolved because I'll resolve and whitelist it within BLE_GAP_EVT_ADV_REPORT handler by myself.

Parents
  • Hi,

    I am having some problems getting a clear picture of what you want to do. Can you explain in a bit more detail?

    Based on the topic, it seems to me that the nRF is a peripheral, and you ask how it can do central address resolution?

    How to push Initiator to resolve its private address (seen at direct_addr of adv_report) when bonded private Advertiser does a direct advertising?

    Here it seems like you are working on the central, and want to check if an advertisement packet is for you, but I am not sure.

    I need the only Initiator's own address to be resolved (based on device IRK) because I use software whitelisting for the reason of more than 8 peers so I don't call sd_ble_gap_whitelist_set() nether sd_ble_gap_device_identities_set(). As a consequence of no calls of these functions BLE_GAP_EVT_ADV_REPORT isn't fired when scan filter is BLE_GAP_SCAN_FP_ACCEPT_ALL. To receive adv reports filter should be changed to BLE_GAP_SCAN_FP_ALL_NOT_RESOLVED_DIRECTED but sd_ble_gap_connect() doesn't accept such setup.

    My understating here is this:

    • An nRF is a central/initiator that use privacy (changes address regularly based on IRK)
    • The peripherals will do directed advertising towards the nRF (using address obtained by central address resolution?)
    • The nRF will accept all directed advertisement packets - no whitelisting is used at the SoftDevice level.

    Is it correct? So the nRF should just check if the advertisement packet was for itself? If so, that should be handled by the SoftDevice provided you set the IRK using sd_ble_gap_privacy_set().

  • nRF should just check if the advertisement packet was for itself?

    Dear Einar, yes, I need exactly that from S132.

    that should be handled by the SoftDevice provided you set the IRK using sd_ble_gap_privacy_set()

    I also expected the same but it's not.

    Steps to reproduce the issue: bond private S112 with private S132, both use sd_ble_gap_privacy_set() for sure, let S112 to advertise directly towards S132, don't use sd_ble_gap_whitelist_set() nether sd_ble_gap_device_identities_set() on S132, observe no adv reports when scan filter is SCAN_FP_ACCEPT_ALL, observe adv reports with unresolved direct_addr when scan filter is SCAN_FP_ALL_NOT_RESOLVED_DIRECTED.

  • Hi,

    I did not get the chance to test this today, but it is a bit surprising. I would have expected the central to resolve the address of the directed advertisement packets automatically (central address resolution), provided you configure privacy using pm_privacy_set() (or sd_ble_gap_privacy_set() directly). As you write, sd_ble_gap_device_identities_set() should not be needed as you don't use whitelisting.

    Do you have the code you used to test this in a state where it can be shared and run on a pair of  DKs? Also, do you have a sniffer trace that shows the initial connection, and then subsequently directed advertisements?

  • Dear Einar, I can't post my code here due to confidentiality. But you may take any pair of central and peripheral examples in SDK then just add few lines to enable the privacy and more detailed log of adv_report. I've not captured any sniffer trace.

    I do also observe one more strange thing related to direct advertising: if identity and white lists are in use, direct_addr in adv_report holds resolvable address and its addr_type is RANDOM_PRIVATE_RESOLVABLE while addr_id_peer is 1, however peer_addr holds identity address, its addr_type is RANDOM_STATIC and addr_id_peer is 1.

  • Dear Einar, enough time have passed. Do you have any progress here?

    Please let me know if there's a dedicated bug report thread, I'll post my observations there.

Reply Children
  • Hi,

    I am sorry for the late reply. I have been testing a bit and discussing with a SoftDevice developer, but we are not sure what is happening.

    A common problem when you want to advertise to the initiator's resolvable address is that you must make sure that your own address is also resolvable. This does not seem to be the problem in this case since you wrote "both use sd_ble_gap_privacy_set()", though.

    Would it be possible for you to make the small modifications to the example that you described so that we know that we are looking at the same code as you are?

    Edit: Can you verify that the address type in the call to sd_ble_gap_privacy_set() is BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE in both ends?

  • Dear Einar, may I know what you've tested exactly? Have you got a setup/code which meets your expectation or BLE specification? I do still prefer you to take a pair of examples from SDK, enable the privacy on both ends then check how the direct advertising works - this will be a really clear test.

    My central and peripherals use the same code to enable the privacy:

    ble_gap_privacy_params_t privacy_params = {0};
    
    privacy_params.privacy_mode      = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY;
    privacy_params.private_addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE;
    APP_ERROR_CHECK(sd_ble_gap_privacy_set(&privacy_params));

  • Hi,

    I have tested with the following central and peripheral modifications from the HRS examples in SDK 15.3 and see similar behavior, but I have not understood what causes this. I am discussing with the SoftDevice team, so hopefully, we should have some results soon.

    diff --git a/examples/ble_peripheral/ble_app_hrs/main.c b/examples/ble_peripheral/ble_app_hrs/main.c
    index 9b0167e..3363c32 100644
    --- a/examples/ble_peripheral/ble_app_hrs/main.c
    +++ b/examples/ble_peripheral/ble_app_hrs/main.c
    @@ -85,7 +85,7 @@
     #define DEVICE_NAME                         "Nordic_HRM"                            /**< Name of device. Will be included in the advertising data. */
     #define MANUFACTURER_NAME                   "NordicSemiconductor"                   /**< Manufacturer. Will be passed to Device Information Service. */
     #define APP_ADV_INTERVAL                    300                                     /**< The advertising interval (in units of 0.625 ms. This value corresponds to 187.5 ms). */
    -
    +#define APP_ADV_DIRECT_INTERVAL                    300                                     /**< The advertising interval (in units of 0.625 ms. This value corresponds to 187.5 ms). */
     #define APP_ADV_DURATION                    18000                                   /**< The advertising duration (180 seconds) in units of 10 milliseconds. */
     
     #define APP_BLE_CONN_CFG_TAG                1                                       /**< A tag identifying the SoftDevice BLE configuration. */
    @@ -121,7 +121,7 @@
     
     #define SEC_PARAM_BOND                      1                                       /**< Perform bonding. */
     #define SEC_PARAM_MITM                      0                                       /**< Man In The Middle protection not required. */
    -#define SEC_PARAM_LESC                      1                                       /**< LE Secure Connections enabled. */
    +#define SEC_PARAM_LESC                      0                                       /**< LE Secure Connections enabled. */
     #define SEC_PARAM_KEYPRESS                  0                                       /**< Keypress notifications not enabled. */
     #define SEC_PARAM_IO_CAPABILITIES           BLE_GAP_IO_CAPS_NONE                    /**< No I/O capabilities. */
     #define SEC_PARAM_OOB                       0                                       /**< Out Of Band data not available. */
    @@ -129,7 +129,7 @@
     #define SEC_PARAM_MAX_KEY_SIZE              16                                      /**< Maximum encryption key size. */
     
     #define DEAD_BEEF                           0xDEADBEEF                              /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */
    -
    +static uint32_t m_peer_count = 0;
     
     BLE_HRS_DEF(m_hrs);                                                 /**< Heart rate service instance. */
     BLE_BAS_DEF(m_bas);                                                 /**< Structure used to identify the battery service. */
    @@ -158,6 +158,8 @@ static ble_uuid_t m_adv_uuids[] =                                   /**< Univers
         {BLE_UUID_DEVICE_INFORMATION_SERVICE,   BLE_UUID_TYPE_BLE}
     };
     
    +static pm_peer_id_t      m_peer_id = PM_PEER_ID_INVALID;                                 /**< Device reference handle to the current bonded central. */
    +
     
     /**@brief Callback function for asserts in the SoftDevice.
      *
    @@ -201,9 +203,19 @@ void advertising_start(bool erase_bonds)
         else
         {
             ret_code_t err_code;
    -
    -        err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
    -        APP_ERROR_CHECK(err_code);
    +    
    +        if (m_peer_count > 0)
    +        {
    +            NRF_LOG_INFO("Start directed advertising");
    +            err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_DIRECTED);
    +            APP_ERROR_CHECK(err_code);
    +        }
    +        else
    +        {
    +            NRF_LOG_INFO("Start fast advertising");
    +            err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
    +            APP_ERROR_CHECK(err_code);
    +        }
         }
     }
     
    @@ -662,15 +674,50 @@ static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
     
         switch (ble_adv_evt)
         {
    +        case BLE_ADV_EVT_DIRECTED_HIGH_DUTY:
    +            NRF_LOG_INFO("High Duty Directed advertising.");
    +            err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING_DIRECTED);
    +            APP_ERROR_CHECK(err_code);
    +            break;
    +
    +        case BLE_ADV_EVT_DIRECTED:
    +            NRF_LOG_INFO("Directed advertising.");
    +            err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING_DIRECTED);
    +            APP_ERROR_CHECK(err_code);
    +            break;
    +
             case BLE_ADV_EVT_FAST:
                 NRF_LOG_INFO("Fast advertising.");
                 err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
                 APP_ERROR_CHECK(err_code);
                 break;
     
    -        case BLE_ADV_EVT_IDLE:
    -            sleep_mode_enter();
    -            break;
    +        case BLE_ADV_EVT_PEER_ADDR_REQUEST:
    +        {
    +            NRF_LOG_INFO("Peer addr request");
    +            
    +            pm_peer_data_bonding_t peer_bonding_data;
    +
    +            if (m_peer_id == PM_PEER_ID_INVALID)
    +            {
    +                m_peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID);
    +            }
    +
    +            // Only Give peer address if we have a handle to the bonded peer.
    +            if (m_peer_id != PM_PEER_ID_INVALID)
    +            {
    +                err_code = pm_peer_data_bonding_load(m_peer_id, &peer_bonding_data);
    +                if (err_code != NRF_ERROR_NOT_FOUND)
    +                {
    +                    APP_ERROR_CHECK(err_code);
    +
    +                    ble_gap_addr_t * p_peer_addr = &(peer_bonding_data.peer_ble_id.id_addr_info);
    +                    err_code = ble_advertising_peer_addr_reply(&m_advertising, p_peer_addr);
    +                    APP_ERROR_CHECK(err_code);
    +                }
    +            }
    +            
    +        } break; //BLE_ADV_EVT_PEER_ADDR_REQUEST
     
             default:
                 break;
    @@ -690,7 +737,8 @@ static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
         switch (p_ble_evt->header.evt_id)
         {
             case BLE_GAP_EVT_CONNECTED:
    -            NRF_LOG_INFO("Connected.");
    +            NRF_LOG_INFO("Connected. Type: %u. Addr:", p_ble_evt->evt.gap_evt.params.connected.peer_addr.addr_type);
    +            NRF_LOG_HEXDUMP_INFO(p_ble_evt->evt.gap_evt.params.connected.peer_addr.addr, BLE_GAP_ADDR_LEN);
                 err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
                 APP_ERROR_CHECK(err_code);
                 m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
    @@ -783,6 +831,12 @@ static void ble_stack_init(void)
     
         // Register a handler for BLE events.
         NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
    +
    +    // Configure privacy
    +    pm_privacy_params_t privacy_params = {0};
    +    privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY;
    +    privacy_params.private_addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE;
    +    pm_privacy_set(&privacy_params);
     }
     
     
    @@ -875,6 +929,10 @@ static void advertising_init(void)
         init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
         init.advdata.uuids_complete.p_uuids  = m_adv_uuids;
     
    +    init.config.ble_adv_directed_enabled  = true;
    +    init.config.ble_adv_directed_high_duty_enabled = true;
    +    init.config.ble_adv_directed_interval          = APP_ADV_DIRECT_INTERVAL;
    +    init.config.ble_adv_directed_timeout           = 1000;
         init.config.ble_adv_fast_enabled  = true;
         init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
         init.config.ble_adv_fast_timeout  = APP_ADV_DURATION;
    @@ -939,10 +997,7 @@ static void idle_state_handle(void)
         err_code = nrf_ble_lesc_request_handler();
         APP_ERROR_CHECK(err_code);
     
    -    if (NRF_LOG_PROCESS() == false)
    -    {
    -        nrf_pwr_mgmt_run();
    -    }
    +    nrf_pwr_mgmt_run();
     }
     
     
    @@ -966,8 +1021,13 @@ int main(void)
         conn_params_init();
         peer_manager_init();
     
    +
         // Start execution.
         NRF_LOG_INFO("Heart Rate Sensor example started.");
    +
    +    m_peer_count = pm_peer_count();
    +    NRF_LOG_INFO("Peer count: %u", m_peer_count);
    +
         application_timers_start();
         advertising_start(erase_bonds);
     
    

    diff --git a/examples/ble_central/ble_app_hrs_c/main.c b/examples/ble_central/ble_app_hrs_c/main.c
    index 3325cfd..2954d70 100644
    --- a/examples/ble_central/ble_app_hrs_c/main.c
    +++ b/examples/ble_central/ble_app_hrs_c/main.c
    @@ -85,7 +85,7 @@
     
     #define SEC_PARAM_BOND              1                                   /**< Perform bonding. */
     #define SEC_PARAM_MITM              0                                   /**< Man In The Middle protection not required. */
    -#define SEC_PARAM_LESC              1                                   /**< LE Secure Connections enabled. */
    +#define SEC_PARAM_LESC              0                                   /**< LE Secure Connections enabled. */
     #define SEC_PARAM_KEYPRESS          0                                   /**< Keypress notifications not enabled. */
     #define SEC_PARAM_IO_CAPABILITIES   BLE_GAP_IO_CAPS_NONE                /**< No I/O capabilities. */
     #define SEC_PARAM_OOB               0                                   /**< Out Of Band data not available. */
    @@ -904,7 +904,6 @@ static void idle_state_handle(void)
         err_code = nrf_ble_lesc_request_handler();
         APP_ERROR_CHECK(err_code);
         
    -    NRF_LOG_FLUSH();
         nrf_pwr_mgmt_run();
     }
     
    @@ -930,6 +929,28 @@ void scanning_start(bool * p_erase_bonds)
     }
     
     
    +void use_privacy(void)
    +{
    +    ret_code_t err_code;
    +
    +    // Configure privacy
    +    pm_privacy_params_t privacy_params = {0};
    +    privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY;
    +    privacy_params.private_addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE;
    +    pm_privacy_set(&privacy_params);
    +
    +    // Log IRK in order to use it in peripheral
    +    ble_gap_privacy_params_t current_privacy_params = {0};
    +    ble_gap_irk_t 	         curretn_irk = {0};
    +    current_privacy_params.p_device_irk = &curretn_irk;
    +    err_code = sd_ble_gap_privacy_get(&current_privacy_params);
    +    APP_ERROR_CHECK(err_code);
    +    
    +    NRF_LOG_INFO("Own IRK:");
    +    NRF_LOG_HEXDUMP_INFO(current_privacy_params.p_device_irk, 16);
    +}
    +
    +
     int main(void)
     {
         bool erase_bonds;
    @@ -942,6 +963,9 @@ int main(void)
         ble_stack_init();
         gatt_init();
         peer_manager_init();
    +
    +    use_privacy();
    +
         db_discovery_init();
         hrs_c_init();
         bas_c_init();
    

  • Dear Einar, have you also checked the second issue I pointed here? I suspect both issues share the same deep root in SoftDevice.

  • Hi,

    Yes, I saw that as well. Some of the developers in the SoftDevice team are looking more into this now. I will keep you posted.

Related