This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Directed advertising with pre-shared IRK

Hello, I'd like to do directed avertising to a central which has a random private resolvable address. My idea: both devices share a pre-defined IRK so the peripheral can compute the central's address and start advertising to this address. According to the core specs v4.2 this should be possible.

p.118: An initiator that receives a directed connectable advertising event that contains a resolvable private address for the initiator’s address, (InitA field) shall resolve the private address using the Local IRK values (see Section 1.3.2.3)

I've modified the central and peripheral examples of the experimental ble_app_blinky so I can work with directed advertising and this setup is working fine when using random static addresses. But as soon as I activate privacy on the central, the central does not react to advertising (i.e. no bluetooth stack event is generated).

On the central I'm using the following code to set privacy:

privacy.privacy_mode = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY;
privacy.private_addr_cycle_s = 15*60;
privacy.private_addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE;
privacy.p_device_irk = &irk;
sd_ble_gap_privacy_set(&privacy);

On the peripheral I start advertising as follows:

generate_hash(prand,hash,irk);   // generates correct hash, verified
peer_addr.addr_type=BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE;
peer_addr.addr[0]=hash[0];
peer_addr.addr[1]=hash[1];
peer_addr.addr[2]=hash[2];
peer_addr.addr[3]=prand[0];
peer_addr.addr[4]=prand[1];
peer_addr.addr[5]=prand[2];  // 0b01xxxxxx

memset(&adv_params, 0, sizeof(adv_params));
adv_params.type        = BLE_GAP_ADV_TYPE_ADV_DIRECT_IND; 
adv_params.p_peer_addr = &peer_addr;
adv_params.fp          = BLE_GAP_ADV_FP_ANY;
adv_params.interval    = APP_ADV_INTERVAL;
adv_params.timeout     = APP_ADV_TIMEOUT_IN_SECONDS;
err_code = sd_ble_gap_adv_start(&adv_params);

What am I missing?

nrf52 S132 SoftDevice v3.0.0 API

  • Seems to be working.

    For the peripheral:

    ret_code_t err_code;
    
    const ble_gap_id_key_t m_peer1 = 
    {
        .id_info =
        {
            .irk = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F},
        }
    };
    
    const ble_gap_id_key_t * m_identities[] = {&m_peer1};
    
    err_code = sd_ble_gap_device_identities_set(m_identities, NULL, 1);
    APP_ERROR_CHECK(err_code);
    
    ble_gap_addr_t gap_addr = 
    {
        .addr_id_peer = 0,
    };
    
    ble_gap_adv_params_t adv_params;
    
    memset(&adv_params, 0, sizeof(adv_params));
    adv_params.type        = BLE_GAP_ADV_TYPE_ADV_DIRECT_IND; 
    adv_params.p_peer_addr = &gap_addr;
    
    err_code = sd_ble_gap_adv_start(&adv_params);
    APP_ERROR_CHECK(err_code);
    

    For the central:

    uint32_t err_code;
    
    ble_gap_irk_t irk = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
    
    ble_gap_privacy_params_t privacy_params;
    privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY;
    
    privacy_params.private_addr_cycle_s = 15*60;
    privacy_params.private_addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE;
    privacy_params.p_device_irk = &irk;
    
    err_code = sd_ble_gap_privacy_set(&privacy_params);
    APP_ERROR_CHECK(err_code);
    
    m_scan_param.active   = 0;
    m_scan_param.interval = SCAN_INTERVAL;
    m_scan_param.window   = SCAN_WINDOW;
    m_scan_param.timeout  = 0x0000;
    
    m_scan_param.use_whitelist  = 0;
    m_scan_param.adv_dir_report = 1;
    
    err_code = sd_ble_gap_scan_start(&m_scan_param);
    APP_ERROR_CHECK(err_code);
    
  • Yep, that's working! I was not aware of the adv_dir_report member of ble_gap_scan_params_t struct. Setting this to one did the trick. Thanks a lot for your help.

Related