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

Can't connect from Android Central when using whitelist on Peripheral

We're trying to use multiple nRF52833 devices with a single BLE Central (Android tablet) where the devices remain disconnected most of the time, and report back to the central through manufacturer-specific data in their advertisements. From time to time, the Android tablet may connect to specific devices to send commands - it disconnects again afterward.

These devices are using softdevice S140 and nRF SDK v16.0.

We'd like to restrict the centrals that may connect to each device, and I think that means using a whitelist. So far, Android is able to connect and bond when there is an empty whitelist, or when advertising without one. We're following the example here.

static const ble_adv_modes_config_t default_advertising_config{
.ble_adv_on_disconnect_disabled = false,
.ble_adv_whitelist_enabled = true,
.ble_adv_directed_high_duty_enabled = false,
.ble_adv_directed_enabled = false,
.ble_adv_fast_enabled = false,
.ble_adv_slow_enabled = true,
.ble_adv_directed_interval = 0,
.ble_adv_directed_timeout = 0,
.ble_adv_fast_interval = APP_ADV_INTERVAL,
.ble_adv_fast_timeout = TIMEOUT_FROM_S(APP_ADV_TIMEOUT_IN_SECONDS),
.ble_adv_slow_interval = APP_ADV_INTERVAL_SLOW,
.ble_adv_slow_timeout = TIMEOUT_FROM_S(APP_ADV_TIMEOUT_SLOW_IN_SECONDS),
.ble_adv_extended_enabled = false,
.ble_adv_secondary_phy = BLE_GAP_PHY_AUTO,
.ble_adv_primary_phy = BLE_GAP_PHY_AUTO,
};
static uint32_t whitelist_peers() {
// Fetch a list of peer IDs from Peer Manager and whitelist them.
pm_peer_id_t peer_ids[BLE_GAP_WHITELIST_ADDR_MAX_COUNT];
uint32_t n_peer_ids = BLE_GAP_WHITELIST_ADDR_MAX_COUNT;

VERIFY_SUCCESS(pm_peer_id_list(peer_ids, &n_peer_ids, PM_PEER_ID_INVALID, PM_PEER_ID_LIST_ALL_ID));
NRF_LOG_DEBUG("Whitelisted %d peers", n_peer_ids);

return pm_whitelist_set(peer_ids, n_peer_ids);
}

static void adv_evt_handler(ble_adv_evt_t ble_adv_evt) {
switch (ble_adv_evt) {
case BLE_ADV_EVT_WHITELIST_REQUEST: {
NRF_LOG_DEBUG("Whitelist requested");
// When the Advertising module is about to advertise, an event
// will be received by the application. In this event, the application
// retrieves a whitelist from the Peer Manager, based on the peers
// previously whitelisted using pm_whitelist_set().
ret_code_t err_code;
// Storage for the whitelist.
ble_gap_irk_t irks[BLE_GAP_WHITELIST_ADDR_MAX_COUNT] = {0};
ble_gap_addr_t addrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT] = {0};
uint32_t irk_cnt = BLE_GAP_WHITELIST_ADDR_MAX_COUNT;
uint32_t addr_cnt = BLE_GAP_WHITELIST_ADDR_MAX_COUNT;
err_code = pm_whitelist_get(addrs, &addr_cnt, irks, &irk_cnt);
APP_ERROR_CHECK(err_code);
// Apply the whitelist.
err_code = ble_advertising_whitelist_reply(&m_advertising, addrs, addr_cnt, irks, irk_cnt);
APP_ERROR_CHECK(err_code);
} break;

default:
break;
}
}

uint32_t set_pair_mode() {
NRF_LOG_DEBUG("enabling pair mode");
VERIFY_SUCCESS(ble_advertising_restart_without_whitelist(&m_advertising));
return NRF_SUCCESS;
}

Once the whitelist is populated though, Android won't connect to the peripheral anymore, even though its address and IRK are in the whitelist. Symptoms are similar to this post, both in the nRF Connect app and our custom UI. The only difference is that we're not using a hardcoded address; peer information is retrieved from the peer manager.

It's almost as if Android sees that no discoverable flags are set in advertisements, and refuses to even try to connect. It instead returns the enigmatic "Error 133".

Is this the correct way to achieve this goal? The only other option I can see is to not use a whitelist and instead disconnect any centrals that are not bonded when they connect.

Thank you!

Parents
  • Hi,

    This looks correct. However, I do not see relevant parts of the peer manager configuration.

    Two things:

    1. Can you show how you initialize the peer manager? For instance what are your security parameters? Particularly, the kdist_own.id and kdist_peer.id should be 1. You can refer to how this is done in examples\ble_peripheral\ble_app_gls\main.c. This may all be fine, but I cannot see it in your snippet so it would be good to check.
    2. Can you log the IRK count and address count you get from pm_whitelist_get()? Are those as expected (with one bonded phone, you should have 1 IRK)
  • Here is how the peer manager is initialized:

    static void peer_manager_init(void) {
    APP_ERROR_CHECK(pm_init());

    // Security parameters to be used for all security procedures.
    ble_gap_sec_params_t sec_param = {
    .bond = 1,
    .mitm = 0,
    .lesc = 1,
    .keypress = 0,
    .io_caps = BLE_GAP_IO_CAPS_NONE,
    .oob = 0,
    .min_key_size = 7,
    .max_key_size = 16,
    .kdist_own =
    {
    .enc = 1,
    .id = 1,
    },
    .kdist_peer =
    {
    .enc = 1,
    .id = 1,
    },
    };

    APP_ERROR_CHECK(pm_sec_params_set(&sec_param));

    APP_ERROR_CHECK(pm_register(pm_evt_handler));
    }

    IRK count and Address count are both 1 from pm_whitelist_get(). I logged the value of the address as well, and it matched the Bluetooth hardware address listed in Android settings.

  • I see. This should work, then. Can you make a sniffer trace? It would be interesting to see how this looks like on air, and if the Android device actually attempts to connect or not. Also, if you have any other central you can test with, that could also be good.

  • The sniffer trace seems to show that Android is trying to connect to the device, but the device doesn't respond. In fact it doesn't send any packets at all for ~5s.

    Active scanning responses do come back though, even for centrals not on the whitelist, but maybe that's correct?

Reply
  • The sniffer trace seems to show that Android is trying to connect to the device, but the device doesn't respond. In fact it doesn't send any packets at all for ~5s.

    Active scanning responses do come back though, even for centrals not on the whitelist, but maybe that's correct?

Children
  • Hi,

    This is the expected behavior when using whitelist and the device is not in the whitelist. I think I see the issue though, which I overlooked earlier. If the code snippet from your original post is complete in lacks an important part, which sis setting the identity list. This is the list of IRKs used by the SoftDevice to resolve the identities of peers using privacy (like Android phones). So even if you get the IRK from the bonding procedure, I suspect that you do not actually use it? I suggest you refer to an SDK example, for instance examples\ble_peripheral\experimental\ble_app_cgms\main.c, and see how that implements the identities_set() function. You need to do the same in your application.

Related