Scanning module

The scanning module handles the Bluetooth® Low Energy scanning for your application.

Overview

Use the scanning module to find advertising devices and establish connections with them. The module can automatically establish connection after a filter match. It can also receive directed advertising packets.

The scanning module can work in one of the following modes:

  • Simple mode - Works without filters.

  • Advanced mode - Allows using advanced filters.

Configuration

Use the CONFIG_BT_SCAN Kconfig option to enable the library in the build system.

Blocklist

Devices can be added to the blocklist, which means that the scanning module ignores these devices and does not generate any events for them. Use the CONFIG_BT_SCAN_BLOCKLIST Kconfig option to enable the blocklist.

In the default configuration, the scanning module allows to add up to two devices to the blocklist. To increase the blocklist size, set the CONFIG_BT_SCAN_BLOCKLIST_LEN Kconfig option. Use the bt_scan_blocklist_device_add() function to add a new device to the blocklist. To remove all devices from the blocklist, use the bt_scan_blocklist_clear() function.

Directed advertising

To receive directed advertising packets through the scanning module, enable one of the following Kconfig options in Zephyr:

It is recommended to enable the CONFIG_BT_PRIVACY Kconfig option to support directed advertising only between bonded peers. Use the CONFIG_BT_SCAN_WITH_IDENTITY Kconfig option only when the CONFIG_BT_PRIVACY Kconfig option is not available.

When the scanning module is set to the advanced mode and filters are set, you can use the filter_no_match event to check if directed advertising packets have been received. They will typically not match any filter as, by specification, they do not contain any advertising data.

If there is no match, you can establish a connection without the need to disable or reconfigure the existing filters.

The following code sample demonstrates the usage of the filter_no_match event:

static void scan_filter_no_match(struct bt_scan_device_info *device_info,
				 bool connectable)
{
	int err;
	struct bt_conn *conn;
	char addr[BT_ADDR_LE_STR_LEN];

	if (device_info->recv_info->adv_type == BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
		bt_addr_le_to_str(device_info->recv_info->addr, addr,
				  sizeof(addr));
		printk("Direct advertising received from %s\n", addr);
		bt_scan_stop();

		err = bt_conn_le_create(device_info->recv_info->addr,
					BT_CONN_LE_CREATE_CONN,
					device_info->conn_param, &conn);

		if (!err) {
			default_conn = bt_conn_ref(conn);
			bt_conn_unref(conn);
		}
	}
}

Usage

You can use the scanning module to execute actions described in the sections below.

Initializing

To initialize the module, call the bt_scan_init() function.

You can also call the function without an initialization structure. When you pass the initialization structure as NULL, the default static configuration is used.

This configuration is also used when you initialize the module with a structure that has NULL pointers set for scan and connection parameters.

Scanning

Call the following functions to perform basic scanning activities:

  • bt_scan_start() - Start scanning.

    In the simple mode, when you do not use the event handler, you can establish a connection when the scanner finds the device.

  • bt_scan_params_set() - Change parameters.

  • bt_scan_stop() - Stop scanning manually.

    Scanning stops automatically if the module established the connection.

  • bt_scan_start() - Resume scanning.

Filtering

Use filters in the advanced mode to narrow down the scan to devices of a specific type and mode.

Filter types

See the following table for the details on the available filter types:

Filter type

Details

Name

The filter is set to the target name.

Short name

The filter is set to the target short name.

Address

The filter is set to the target address.

UUID

The filter is set to the target UUID.

Appearance

The filter is set to the target appearance.

Filter modes

See the following table for the details on the behavior of the available filter modes:

Filter mode

Behavior

Normal

It triggers a filter match callback when only one of the filters set matches, regardless of the type.

Multifilter

It triggers a filter match callback only when both of the following conditions happen:

  • All specified UUIDs match.

  • At least one filter for each of the filter types set matches.

For example, several filters can be set for name, address, UUID, and appearance. To trigger a filter match callback in this scenario, all of the following types must match:

  • At least one of the address filters

  • At least one of the name filters

  • At least one of the appearance filters

  • All of the UUID filters

If not all of these types match, the not found callback is triggered.

Connection attempts filter

After a scanning session is started by the application, some peripheral devices can disconnect immediately. This might result in a loop of the connection and disconnection events.

To avoid that, enable the CONFIG_BT_SCAN_CONN_ATTEMPTS_FILTER Kconfig option that limits the number of the connection attempts.

This filter automatically tracks the connected devices and counts all disconnection events for them. If the number of disconnections is greater than or equal to the number of the allowed attempts, the scanning module ignores this device.

Filtered devices must be removed manually from the filter array through the bt_scan_conn_attempts_filter_clear() function. Use this function before each scan starts, unless your application has different requirements. If the filter array is full, the scanning module overwrites the oldest device with the new one.

In the default configuration, the filter allows to add two devices and limits the connection attempts to two. To increase the number of devices, set the CONFIG_BT_SCAN_CONN_ATTEMPTS_FILTER_LEN Kconfig option. The CONFIG_BT_SCAN_CONN_ATTEMPTS_COUNT Kconfig option adjusts the number of connection attempts.

Samples using the library

The following nRF Connect SDK application uses this library:

Dependencies

There are no dependencies for using this library.

API documentation

Header file: include/bluetooth/scan.h
Source file: subsys/bluetooth/scan.c
group nrf_bt_scan

BT Scanning module.

The Scanning Module handles the Bluetooth LE scanning for your application. The module offers several criteria for filtering the devices available for connection, and it can also work in the simple mode without using the filtering. If an event handler is provided, your main application can react to a filter match. The module can also be configured to automatically connect after it matches a filter.

Note

The Scanning Module also supports applications with a multicentral link.

Defines

BT_SCAN_CB_INIT(_name, match_fun, no_match_fun, error_fun, connecting_fun)

Initializing macro for scanning module.

This is macro initializing necessary structures for bt_scan_cb type.

Parameters
  • _name[in] Unique name for bt_scan_cb structure.

  • match_fun[in] Scan filter matched function pointer.

  • no_match_fun[in] Scan filter unmatched (the device was not found) function pointer.

  • error_fun[in] Error when connecting function pointer.

  • connecting_fun[in] Connecting data function pointer.

Enums

enum bt_scan_type

Scan types.

Values:

enumerator BT_SCAN_TYPE_SCAN_PASSIVE

Passive scanning.

enumerator BT_SCAN_TYPE_SCAN_ACTIVE

Active scanning.

enum bt_scan_filter_type

Types of filters.

Values:

enumerator BT_SCAN_FILTER_TYPE_NAME

Filter for names.

enumerator BT_SCAN_FILTER_TYPE_SHORT_NAME

Filter for short names.

enumerator BT_SCAN_FILTER_TYPE_ADDR

Filter for addresses.

enumerator BT_SCAN_FILTER_TYPE_UUID

Filter for UUIDs.

enumerator BT_SCAN_FILTER_TYPE_APPEARANCE

Filter for appearances.

enumerator BT_SCAN_FILTER_TYPE_MANUFACTURER_DATA

Filter for manufacturer data.

Functions

void bt_scan_cb_register(struct bt_scan_cb *cb)

Register scanning callbacks.

Register callbacks to monitor the state of scanning.

Parameters
  • cb – Callback struct.

void bt_scan_init(const struct bt_scan_init_param *init)

Function for initializing the Scanning Module.

Parameters
  • init[in] Pointer to scanning module initialization structure. Can be initialized as NULL. If NULL, the parameters required to initialize the module are loaded from static configuration. If module is to establish the connection automatically, this must be initialized with the relevant data.

int bt_scan_start(enum bt_scan_type scan_type)

Function for starting scanning.

This function starts the scanning according to the configuration set during the initialization.

Parameters
  • scan_type[in] The choice between active and passive scanning.

Returns

0 If the operation was successful. Otherwise, a (negative) error code is returned.

int bt_scan_stop(void)

Function for stopping scanning.

void bt_scan_update_init_conn_params(struct bt_le_conn_param *new_conn_param)

Function to update initial connection parameters.

Note

The function should not be used when scanning is active.

Parameters
  • new_conn_param[in] New initial connection parameters.

int bt_scan_filter_enable(uint8_t mode, bool match_all)

Function for enabling filtering.

The filters can be combined with each other. For example, you can enable one filter or several filters. For example, (BT_SCAN_NAME_FILTER | BT_SCAN_UUID_FILTER) enables UUID and name filters.

Parameters
  • mode[in] Filter mode: Filter modes.

  • match_all[in] If this flag is set, all types of enabled filters must be matched before generating BT_SCAN_EVT_FILTER_MATCH to the main application. Otherwise, it is enough to match one filter to trigger the filter match event.

Returns

0 If the operation was successful. Otherwise, a (negative) error code is returned.

void bt_scan_filter_disable(void)

Function for disabling filtering.

This function disables all filters. Even if the automatic connection establishing is enabled, the connection will not be established with the first device found after this function is called.

int bt_scan_filter_status_get(struct bt_filter_status *status)

Function for getting filter status.

This function returns the filter setting and whether it is enabled or disabled.

Parameters
  • status[out] Pointer to Filter Status structure.

Returns

0 If the operation was successful. Otherwise, a (negative) error code is returned.

int bt_scan_filter_add(enum bt_scan_filter_type type, const void *data)

Function for adding any type of filter to the scanning.

This function adds a new filter by type. The filter will be added if there is available space in this filter type array, and if the same filter has not already been set.

Parameters
  • type[in] Filter type.

  • data[in] Pointer to the filter data to add.

Returns

0 If the operation was successful. Otherwise, a (negative) error code is returned.

void bt_scan_filter_remove_all(void)

Function for removing all set filters.

The function removes all previously set filters.

Note

After using this function the filters are still enabled.

int bt_scan_params_set(struct bt_le_scan_param *scan_param)

Function for changing the scanning parameters.

Use this function to change scanning parameters. During the parameter change the scan is stopped. To resume scanning, use bt_scan_start. Scanning parameters can be set to NULL. If so, the default static configuration is used.

Parameters
  • scan_param[in] Pointer to Scanning parameters. Can be initialized as NULL.

Returns

0 If the operation was successful. Otherwise, a (negative) error code is returned.

void bt_scan_conn_attempts_filter_clear(void)

Clear connection attempts filter.

Use this function to remove all entries from the connection attempts filter.

int bt_scan_blocklist_device_add(const bt_addr_le_t *addr)

Add a new device to the blocklist.

Use this function to add a device to the blocklist. Scanning module does not generate any event for the blocklist device or does not try to connect such devices.

Parameters
  • addr[in] Device address.

Return values

0 – If the operation was successful. Otherwise, a (negative) error code is returned.

void bt_scan_blocklist_clear(void)

Clear the blocklist of the scanning module device.

Use this function to remove all entries from the blocklist.

struct bt_scan_filter_info
#include <scan.h>

Filter information structure.

It contains information about the number of filters of a given type and whether they are enabled

Public Members

bool enabled

Filter enabled.

uint8_t cnt

Filter count.

struct bt_filter_status
#include <scan.h>

Filter status structure.

Public Members

bool all_mode

Filter mode.

struct bt_scan_filter_info name

Name filters info.

struct bt_scan_filter_info short_name

Short name filters info.

struct bt_scan_filter_info addr

Address filters info.

struct bt_scan_filter_info uuid

UUID filters info.

struct bt_scan_filter_info appearance

Appearance filter info.

struct bt_scan_filter_info manufacturer_data

Appearance filter info.

struct bt_scan_adv_info
#include <scan.h>

Advertising info structure.

Public Members

uint8_t adv_type

Bluetooth LE advertising type. According to Bluetooth Specification 7.8.5

int8_t rssi

Received Signal Strength Indication in dBm.

struct bt_scan_short_name
#include <scan.h>

A helper structure to set filters for the name.

Public Members

const char *name

Pointer to the short name.

uint8_t min_len

Minimum length of the short name.

struct bt_scan_manufacturer_data
#include <scan.h>

A helper structure to set filters for the manufacturer data.

Public Members

uint8_t *data

Pointer to the manufacturer data.

uint8_t data_len

Manufacturer data length.

struct bt_scan_init_param
#include <scan.h>

Structure for Scanning Module initialization.

Public Members

const struct bt_le_scan_param *scan_param

Scan parameters required to initialize the module. Can be initialized as NULL. If NULL, the parameters required to initialize the module are loaded from the static configuration.

const struct bt_le_conn_param *conn_param

Connection parameters. Can be initialized as NULL. If NULL, the default static configuration is used.

struct bt_scan_name_filter_status
#include <scan.h>

Name filter status structure, used to inform the application which name filter is matched.

Public Members

bool match

Set to true if this type of filter is matched.

const char *name

Pointer to the matched filter name.

uint8_t len

Length of the matched name.

struct bt_scan_addr_filter_status
#include <scan.h>

Address filter status structure, used to inform the application which address filter is matched.

Public Members

bool match

Set to true if this type of filter is matched.

const bt_addr_le_t *addr

Pointer to the matched filter address.

struct bt_scan_uuid_filter_status
#include <scan.h>

UUID filter status structure, used to inform the application which UUID filters are matched.

Public Members

bool match

Set to true if this type of filter is matched.

const struct bt_uuid *uuid[1]

Array of pointers to the matched UUID filters.

uint8_t count

Matched UUID count.

struct bt_scan_appearance_filter_status
#include <scan.h>

Appearance filter status structure, used to inform the application which appearance filter is matched.

Public Members

bool match

Set to true if this type of filter is matched.

const uint16_t *appearance

Pointer to the matched filter appearance.

struct bt_scan_manufacturer_data_filter_status
#include <scan.h>

Manufacturer data filter status structure, used to inform the application which manufacturer data filter is matched.

Public Members

bool match

Set to true if this type of filter is matched.

const uint8_t *data

Pointer to the matched filter manufacturer data.

uint8_t len

Length of the matched manufacturer data.

struct bt_scan_filter_match
#include <scan.h>

Structure for setting the filter status.

This structure is used for sending filter status to the main application. Filter status contains information about which kind of filter is matched and also appropriate filter data.

Public Members

struct bt_scan_name_filter_status name

Name filter status data.

struct bt_scan_name_filter_status short_name

Short name filter status data.

struct bt_scan_addr_filter_status addr

Address filter status data.

struct bt_scan_uuid_filter_status uuid

UUIDs filter status data.

struct bt_scan_appearance_filter_status appearance

Appearance filter status data.

struct bt_scan_manufacturer_data_filter_status manufacturer_data

Manufacturer data filter status data.

struct bt_scan_device_info
#include <scan.h>

Structure containing device data needed to establish connection and advertising information.

Public Members

const struct bt_le_scan_recv_info *recv_info

Received advertising packet information

const struct bt_le_conn_param *conn_param

Connection parameters for LE connection.

struct net_buf_simple *adv_data

Received advertising data. If further data processing is needed, you should use bt_data_parse() to get specific advertising data type.

struct cb_data
#include <scan.h>

Data for scanning callback structure.

This structure is used for storing callback functions pointers. It is used by bt_scan_cb structure.

Public Members

void (*filter_match)(struct bt_scan_device_info *device_info, struct bt_scan_filter_match *filter_match, bool connectable)

Scan filter matched.

Param device_info

[in] Data needed to establish connection and advertising information.

Param filter_match

[in] Filter match status.

Param connectable

[in] Inform that device is connectable.

void (*filter_no_match)(struct bt_scan_device_info *device_info, bool connectable)

Scan filter unmatched. The device was not found.

Note

Even if the filters are disable and not set, then all devices will be reported by this callback. It can be useful if the scan is used without filters.

Param device_info

[in] Data needed to establish connection and advertising information.

Param connectable

[in] Inform that device is connectable.

struct bt_scan_cb
#include <scan.h>

Scanning callback structure.

This structure is used for tracking the state of a scanning. It is registered with the help of the bt_scan_cb_register() API. It’s permissible to register multiple instances of this bt_scan_cb type, in case different modules of an application are interested in tracking the scanning state. If a callback is not of interest for an instance, it may be set to NULL and will as a consequence not be used for that instance.