Error when loading whitelist on a central + peripheral when connected peripheral shutdowns

Hello,

I have a 52832 using SDK16.0.0, that acts as an advertising peripheral (anyone can connect to it), and as a central, connected with 1-1 bond to a peripheral (a 52811).

I have implemented this 1-1 bond using whitelist and peer_managers on both sides (central 52832 and peripheral 52811). This is based on HRS / HRS_C examples.

Everythings works fine when bonding and keeping connection.

Here is the scenario that doesn't work : when peripheral shutdowns. Then the central starts scanning again, a whitelist request is received, but when loading whitelist I get a 12804 error (BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE) on pm_device_identities_list_set.

If I restart the central with the peripheral still down, I get the same error.
I I restart the central with the peripheral up and avertising, it successfully connects. 

Here are the logs of succcessful initial pairing :

00> <debug> ble_scan: Scanning parameters have been changed successfully
00> <info> app: Whitelist request
00> <debug> ble_scan: Scanning parameters have been changed successfully
00> <debug> ble_scan: Scanning
00> <debug> ble_scan: Connecting
00> <debug> ble_scan: Connection status: 0
00> <info> app: Scan filter match.
00> <info> app: Central connected to Scale (mac address E3:30:0F:54:9A:DC)
00> <info> app: Attempt to find scale peripheral on conn_handle 0x0
00> <debug> nrf_ble_gq: Registering connection handle: 0x0000
00> <debug> ble_db_disc: Starting discovery of service with UUID 0x1 on connection handle 0x0.
00> <debug> nrf_ble_gq: Adding item to the request queue
00> <debug> nrf_ble_gq: GATTC Primary Services Discovery Request
00> <debug> nrf_ble_gq: SD GATT procedure (2) succeeded on connection handle: 0.
00> <debug> ble_db_disc: Found service UUID 0x1.
00> <debug> nrf_ble_gq: Adding item to the request queue
00> <debug> nrf_ble_gq: GATTC Characteristic Discovery Request
00> <debug> nrf_ble_gq: SD GATT procedure (3) succeeded on connection handle: 0.
00> <debug> nrf_ble_gq: Processing the request queue...
00> <debug> nrf_ble_gq: Adding item to the request queue
00> <debug> nrf_ble_gq: GATTC Characteristic Discovery Request
00> <debug> nrf_ble_gq: SD GATT procedure (3) succeeded on connection handle: 0.
00> <debug> nrf_ble_gq: Processing the request queue...
00> <debug> nrf_ble_gq: Adding item to the request queue
00> <debug> nrf_ble_gq: GATTC Characteristic Discovery Request
00> <debug> nrf_ble_gq: SD GATT procedure (3) succeeded on connection handle: 0.
00> <debug> nrf_ble_gq: Processing the request queue...
00> <debug> nrf_ble_gq: Adding item to the request queue
00> <debug> nrf_ble_gq: GATTC Characteristic Descriptor Request
00> <debug> nrf_ble_gq: SD GATT procedure (4) succeeded on connection handle: 0.
00> <debug> nrf_ble_gq: Processing the request queue...
00> <debug> ble_db_disc: Discovery of service with UUID 0x1 completed with success on connection handle 0x0.
00> <debug> app: Scale service discovered.
00> <info> app: Assigning scale ble handles
00> <debug> peer_manager_handler: Event PM_EVT_CONN_SEC_PARAMS_REQ
00> <debug> peer_manager_handler: Security parameter request
00> <debug> peer_manager_handler: Event PM_EVT_CONN_SEC_START
00> <debug> peer_manager_handler: Connection security procedure started: role: Central, conn_handle: 0, procedure: Bonding
00> <debug> nrf_ble_gq: Adding item to the request queue
00> <debug> nrf_ble_gq: GATTC Write Request
00> <debug> nrf_ble_gq: SD GATT procedure (1) succeeded on connection handle: 0.
00> <debug> app: Scale service notifications enabled
00> <debug> nrf_ble_gq: Processing the request queue...
00> <debug> nrf_ble_gq: Processing the request queue...
00> <debug> peer_manager_handler: Event PM_EVT_CONN_SEC_PARAMS_REQ
00> <debug> peer_manager_handler: Security parameter request
00> <debug> peer_manager_handler: Event PM_EVT_CONN_SEC_SUCCEEDED
00> <info> peer_manager_handler: Connection secured: role: Central, conn_handle: 0, procedure: Bonding
00> <info> app: Bonding with previous scale succeded
00> <debug> peer_manager_handler: Event PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
00> <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Bonding data, action: Update
00> <debug> peer_manager_handler: Event PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
00> <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Peer rank, action: Update
00> <debug> peer_manager_handler: Event PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
00> <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Local database, action: Update
00> <debug> app: Received data from BLE BOKS
00> <debug> app:  52                     |R       
00> <debug> nrf_ble_gq: Processing the request queue...
00> <debug> nrf_ble_gq: Processing the request queue...
00> <debug> peer_manager_handler: Event PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
00> <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Central address resolution, action: Update

Here are the logs after shuting down the connected peripheral :

00> <debug> ble_scan: Scanning parameters have been changed successfully
00> <info> app: Whitelist request
00> <error> app: ERROR 12804 [Unknown error code] at ble_scale.c:280
00> PC at: 0x00037529
00> <error> app: End of error report


Here is the relevant code:

static void scan_evt_handler(scan_evt_t const * p_scan_evt)
{
    ret_code_t err_code;
    switch(p_scan_evt->scan_evt_id)
    {
        case NRF_BLE_SCAN_EVT_WHITELIST_REQUEST:
        {
            NRF_LOG_INFO("Whitelist request");
            on_whitelist_req();
        } break;

        (....)
    }
}

static void on_whitelist_req(void)
{
    // Whitelist buffers.
    ble_gap_addr_t whitelist_addrs[8];
    ble_gap_irk_t  whitelist_irks[8];

    memset(whitelist_addrs, 0x00, sizeof(whitelist_addrs));
    memset(whitelist_irks,  0x00, sizeof(whitelist_irks));

    uint32_t addr_cnt = (sizeof(whitelist_addrs) / sizeof(ble_gap_addr_t));
    uint32_t irk_cnt  = (sizeof(whitelist_irks)  / sizeof(ble_gap_irk_t));

    // Reload the whitelist and whitelist all peers.
    whitelist_load();

    ret_code_t ret;

    // Get the whitelist previously set with pm_whitelist_set().
    ret = pm_whitelist_get(whitelist_addrs, &addr_cnt,
                           whitelist_irks,  &irk_cnt);

    if (((addr_cnt == 0) && (irk_cnt == 0)))
    {
        m_scan_param.filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL;

        ret = nrf_ble_scan_params_set(&m_scan, &m_scan_param);
        APP_ERROR_CHECK(ret);
    }
}

static void whitelist_load()
{
    ret_code_t   ret;
    pm_peer_id_t peers[8];
    uint32_t     peer_cnt;

    memset(peers, PM_PEER_ID_INVALID, sizeof(peers));
    peer_cnt = (sizeof(peers) / sizeof(pm_peer_id_t));

    // Load all peers from the flash and whitelist them.
    peer_list_get(peers, &peer_cnt);

    ret = pm_whitelist_set(peers, peer_cnt);
    APP_ERROR_CHECK(ret);

    // Setup the list of device identities.
    // Some SoftDevices do not support this feature.
    ret = pm_device_identities_list_set(peers, peer_cnt);
    if (ret != NRF_ERROR_NOT_SUPPORTED)
    {
        APP_ERROR_CHECK(ret);
    }
}

I do not reproduce with HRS / HRS_C examples.

Thanks !

  • Hi Quentin, 

    Could you post your full code in your main.c ? 
    The error you received could be related to that whitelist_load () (which calls pm_device_identities_list_set() ) has been called more than once with the same list. 

    I noticed that in  your log you have "Scanning parameters have been changed successfully" could you check how you get this log ? Usually it's the call nrf_ble_scan_params_set() that should not be called when whitelist is used. (at least in the hrs_c it's not called if there is something in the whitelist)

  • I have also taken inspiration in example rscs_c, where you can find :

    m_scan_param.filter_policy = BLE_GAP_SCAN_FP_WHITELIST;
    err_code = nrf_ble_scan_params_set(&m_scan, &m_scan_param);



    Here is additional code from my project :

    /**< Scan parameters requested for scanning and connection. */
    static ble_gap_scan_params_t m_scan_param =
    {
        .active        = 0x01,
        .interval      = NRF_BLE_SCAN_SCAN_INTERVAL,
        .window        = NRF_BLE_SCAN_SCAN_WINDOW,
        .filter_policy  = BLE_GAP_SCAN_FP_WHITELIST,
        .timeout       = SCAN_DURATION,
        .scan_phys     = BLE_GAP_PHY_1MBPS
        //.extended      = 1 // should it be set ? 
    };
    
    static void scan_start(void)
    {
        ret_code_t err_code;
    
        // If there is any pending write to flash, defer scanning until it completes.
        if (nrf_fstorage_is_busy(NULL))
        {
            m_memory_access_in_progress = true;
            return;
        }
    
        scale_scan_blink_start();
    
        m_scan_param.filter_policy = BLE_GAP_SCAN_FP_WHITELIST;
    
        err_code = nrf_ble_scan_params_set(&m_scan, &m_scan_param);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_ble_scan_start(&m_scan);
        APP_ERROR_CHECK(err_code);
    }

  • Sorry, also the scan initialization : 

    static void scan_init(void)
    {
        ret_code_t err_code;
        nrf_ble_scan_init_t init_scan;
    
        memset(&init_scan, 0, sizeof(init_scan));
    
        init_scan.p_scan_param     = &m_scan_param;
        init_scan.connect_if_match = true;
        init_scan.conn_cfg_tag     = APP_BLE_CONN_CFG_TAG;
    
        err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_ble_scan_filter_set(&m_scan,
                                           SCAN_NAME_FILTER,
                                           "Bala");
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_ble_scan_filters_enable(&m_scan,
                                               NRF_BLE_SCAN_NAME_FILTER,
                                               true);
        APP_ERROR_CHECK(err_code);
    }


    I wish to scan initially all devices with name "Bala", connect when found one, pair to it, add it to whitelist, and from then only scanning this one.

    Maybe I should unset filters when scanning with whitelist ?

  • Please double check if you use filter_policy BLE_GAP_SCAN_FP_WHITELIST in the ble_gap_scan_params_t when you call nrf_ble_scan_params_set()

    I would suggest to step into the code and check if pm_device_identities_list_set() was called twice ? 

    I don't think using filter with whitelist would cause any problem. 

  • Please double check if you use filter_policy BLE_GAP_SCAN_FP_WHITELIST in the ble_gap_scan_params_t when you call nrf_ble_scan_params_set()
    As you can see above, I am setting BLE_GAP_SCAN_FP_WHITELIST only if a peer is present. Is it not the correct thing to do ?

    > check if pm_device_identities_list_set() was called twice
    I have done that, and added logs, it is not called twice.

Related