This blog is to show how to add the scan request filter on the BLE advertiser.

In BLE (bluetooth Low Energy), basically, it has two difference modes on the scanning mode.

On the BLE observer, it can be either passive scanning or active scanning.

If the observer plays as the active scanning, it would send the scan request to get the further advertising payload. The scanner would send the scan request to advertiser and ask for the additional 31 bytes payload (scan response). At that time, this advertiser only responses to such scanner instead of other BLE scanners.

In this blog, I would like to show you how to configure the filter policy on the advertiser on particular scanner with known MAC address.

From Bluetooth specification (BLUETOOTH CORE SPECIFICATION Version 5.1 | Vol 6, Part B), the Advertising event types, PDUs used, and allowable response PDUs.

On the Nordic Softdevice stack, it has the difference filter policies.

/**@defgroup BLE_GAP_ADV_FILTER_POLICIES GAP Advertising filter policies
 * @{ */
#define BLE_GAP_ADV_FP_ANY                0x00   /**< Allow scan requests and connect requests from any device. */
#define BLE_GAP_ADV_FP_FILTER_SCANREQ     0x01   /**< Filter scan requests with whitelist. */
#define BLE_GAP_ADV_FP_FILTER_CONNREQ     0x02   /**< Filter connect requests with whitelist. */
#define BLE_GAP_ADV_FP_FILTER_BOTH        0x03   /**< Filter both scan and connect requests with whitelist. */
/**@} */

If you need to apply the filter policy at the advertiser, you have to configure the advertising mode to non-discoverable mode (BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED).

All the code can be found at my github. (https://github.com/jimmywong2003/nrf5-ble-scan-filter-example)

Advertising with filter

static void advertising_with_filter_init(void)
{
        ret_code_t err_code;
        ble_advdata_t advdata;
        ble_advdata_t srdata;

        //ble_uuid_t adv_uuids[] = {{LBS_UUID_SERVICE, m_lbs.uuid_type}};

        NRF_LOG_INFO("Advertising init");

        // Build and set advertising data.
        memset(&advdata, 0, sizeof(advdata));

        advdata.name_type          = BLE_ADVDATA_FULL_NAME;
        advdata.include_appearance = false;
        advdata.flags              = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;

        memset(&srdata, 0, sizeof(srdata));

        err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
        APP_ERROR_CHECK(err_code);

        err_code = ble_advdata_encode(&srdata, m_adv_data.scan_rsp_data.p_data, &m_adv_data.scan_rsp_data.len);
        APP_ERROR_CHECK(err_code);

        ble_gap_adv_params_t adv_params;

        // Set advertising parameters.
        memset(&adv_params, 0, sizeof(adv_params));

        NRF_LOG_INFO("Set to 1 Mbps");
        adv_params.primary_phy     = BLE_GAP_PHY_1MBPS;
        adv_params.secondary_phy   = BLE_GAP_PHY_1MBPS;
        adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;

        adv_params.duration        = APP_ADV_DURATION;
        adv_params.p_peer_addr     = NULL;
        adv_params.filter_policy   = BLE_GAP_ADV_FP_FILTER_BOTH;//BLE_GAP_ADV_FP_FILTER_SCANREQ;
        adv_params.interval        = APP_ADV_INTERVAL;
        adv_params.scan_req_notification = 1;

        nrf_ble_whitelist_enable();

        err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &adv_params);

        APP_ERROR_CHECK(err_code);

}