Skip to content

Commit d71f75f

Browse files
bluetooth: ble_scan: add manufacturer data filter support
Port the manufacturer data scan filter from NCS to Bare Metal. Adds BLE_SCAN_MANUFACTURER_DATA_FILTER type, manufacturer_data_filter_match flag in ble_scan_filter_match, and plumbing through ble_scan_filter_add, ble_scan_filters_enable, ble_scan_filters_disable, ble_scan_all_filter_remove and the adv report event handler. New Kconfig options: - CONFIG_BLE_SCAN_MANUFACTURER_DATA_COUNT - CONFIG_BLE_SCAN_MANUFACTURER_DATA_MAX_LEN Modified unit tests to align with changes. Added changelog. Signed-off-by: Martynas Smilingis <martynas.smilingis@nordicsemi.no>
1 parent fafb892 commit d71f75f

6 files changed

Lines changed: 459 additions & 9 deletions

File tree

doc/nrf-bm/release_notes/release_notes_changelog.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,13 @@ Libraries
8585

8686
* Added the :c:func:`ble_adv_data_manufacturer_data_find` function to locate manufacturer-specific data in an advertising payload and prefix-match it against a target value.
8787

88+
* :ref:`lib_ble_scan` library:
89+
90+
* Added:
91+
92+
* Support for filtering by manufacturer-specific data using the :c:macro:`BLE_SCAN_MANUFACTURER_DATA_FILTER` filter type.
93+
* The :kconfig:option:`CONFIG_BLE_SCAN_MANUFACTURER_DATA_COUNT` and :kconfig:option:`CONFIG_BLE_SCAN_MANUFACTURER_DATA_MAX_LEN` Kconfig options to configure the manufacturer data filter capacity and maximum payload length.
94+
8895
Bluetooth LE Services
8996
---------------------
9097

include/bm/bluetooth/ble_scan.h

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ enum ble_scan_evt_type {
106106
#define BLE_SCAN_APPEARANCE_FILTER (0x08)
107107
/** Filters the device short name. */
108108
#define BLE_SCAN_SHORT_NAME_FILTER (0x10)
109+
/** Filters the manufacturer data. */
110+
#define BLE_SCAN_MANUFACTURER_DATA_FILTER (0x20)
109111
/** @} */
110112

111113
/**
@@ -136,6 +138,13 @@ struct ble_scan_filter_data {
136138
/** Minimum length of the short name to be matched. */
137139
uint8_t short_name_min_len;
138140
} short_name_filter;
141+
/** Manufacturer filter data */
142+
struct {
143+
/** Pointer to the manufacturer data. */
144+
uint8_t *data;
145+
/** Manufacturer data length. */
146+
uint8_t data_len;
147+
} manufacturer_data_filter;
139148
};
140149
};
141150

@@ -153,6 +162,8 @@ struct ble_scan_filter_match {
153162
uint8_t appearance_filter_match: 1;
154163
/** Set to 1 if short name filter is matched. */
155164
uint8_t short_name_filter_match: 1;
165+
/** Set to 1 if manufacturer data filter is matched. */
166+
uint8_t manufacturer_data_filter_match: 1;
156167
};
157168

158169
/**
@@ -291,6 +302,22 @@ struct ble_scan_appearance_filter {
291302
bool appearance_filter_enabled;
292303
};
293304

305+
/** Scan manufacturer data filter. */
306+
struct ble_scan_manufacturer_data_filter {
307+
struct {
308+
/** Manufacturer data that the main application will scan for, and that will be
309+
* advertised by the peripherals.
310+
*/
311+
uint8_t data[CONFIG_BLE_SCAN_MANUFACTURER_DATA_MAX_LEN];
312+
/** Length of the manufacturer data. */
313+
uint8_t data_len;
314+
} manufacturer_data[CONFIG_BLE_SCAN_MANUFACTURER_DATA_COUNT];
315+
/** Number of manufacturer data in list. */
316+
uint8_t manufacturer_data_cnt;
317+
/** Flag to inform about enabling or disabling this filter. */
318+
bool manufacturer_data_filter_enabled;
319+
};
320+
294321
/**
295322
* @brief Filter data.
296323
*
@@ -320,6 +347,10 @@ struct ble_scan_filters {
320347
#if CONFIG_BLE_SCAN_APPEARANCE_COUNT > 0
321348
/** Appearance filter data. */
322349
struct ble_scan_appearance_filter appearance_filter;
350+
#endif
351+
#if CONFIG_BLE_SCAN_MANUFACTURER_DATA_COUNT > 0
352+
/** Manufacturer filter data. */
353+
struct ble_scan_manufacturer_data_filter manufacturer_data_filter;
323354
#endif
324355
/** Filter mode. If true, all set filters must be matched to generate an event. */
325356
bool all_filters_mode;
@@ -517,8 +548,9 @@ uint32_t ble_scan_filter_get(const struct ble_scan *scan, struct ble_scan_filter
517548
* This function adds a new filter by type @ref ble_scan_filter_type.
518549
* The filter will be added if the number of filters of a given type does not exceed @ref
519550
* CONFIG_BLE_SCAN_UUID_COUNT, @ref CONFIG_BLE_SCAN_NAME_COUNT, @ref
520-
* CONFIG_BLE_SCAN_ADDRESS_COUNT, or @ref CONFIG_BLE_SCAN_APPEARANCE_COUNT, depending on
521-
* the filter type, and if the same filter has not already been set.
551+
* CONFIG_BLE_SCAN_ADDRESS_COUNT, @ref CONFIG_BLE_SCAN_APPEARANCE_COUNT,
552+
* or @ref BLE_SCAN_MANUFACTURER_DATA_COUNT, depending on the filter type,
553+
* and if the same filter has not already been set.
522554
*
523555
* @param[in,out] scan Scan library instance.
524556
* @param[in] type Filter type.

lib/bluetooth/ble_scan/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ config BLE_SCAN_SHORT_NAME_MAX_LEN
3030
help
3131
Maximum size of the short name to search for in the advertisement report.
3232

33+
config BLE_SCAN_MANUFACTURER_DATA_MAX_LEN
34+
int "Scan manufacturer data maximum length"
35+
default 32
36+
help
37+
Maximum size for the manufacturer data to search in the advertisement report.
38+
3339
config BLE_SCAN_FILTER
3440
bool "Scan filter"
3541
default y
@@ -68,6 +74,12 @@ config BLE_SCAN_UUID_COUNT
6874
help
6975
Maximum number of filters for UUIDs.
7076

77+
config BLE_SCAN_MANUFACTURER_DATA_COUNT
78+
int "Scan manufacturer data count"
79+
default 0
80+
help
81+
Maximum number of manufacturer data filters.
82+
7183
endif # BLE_SCAN_FILTER
7284

7385
config BLE_SCAN_INTERVAL

lib/bluetooth/ble_scan/ble_scan.c

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,68 @@ static int appearance_filter_add(struct ble_scan *scan, const struct ble_scan_fi
362362
}
363363
#endif /* CONFIG_BLE_SCAN_APPEARANCE_COUNT */
364364

365+
#if (CONFIG_BLE_SCAN_MANUFACTURER_DATA_COUNT > 0)
366+
static bool adv_manufacturer_data_compare(const struct ble_scan *scan,
367+
uint8_t *data, uint16_t len)
368+
{
369+
const struct ble_scan_manufacturer_data_filter *md_filter =
370+
&scan->scan_filters.manufacturer_data_filter;
371+
372+
/* Match the adv packet against each configured manufacturer data filter. */
373+
for (uint8_t i = 0; i < md_filter->manufacturer_data_cnt; i++) {
374+
if (ble_adv_data_manufacturer_data_find(data, len,
375+
md_filter->manufacturer_data[i].data,
376+
md_filter->manufacturer_data[i].data_len)) {
377+
return true;
378+
}
379+
}
380+
return false;
381+
}
382+
383+
static int manufacturer_data_filter_add(struct ble_scan *scan,
384+
const struct ble_scan_filter_data *data)
385+
{
386+
struct ble_scan_manufacturer_data_filter *md_filter =
387+
&scan->scan_filters.manufacturer_data_filter;
388+
uint8_t *counter = &md_filter->manufacturer_data_cnt;
389+
uint8_t md_len = data->manufacturer_data_filter.data_len;
390+
uint8_t *md_data = data->manufacturer_data_filter.data;
391+
392+
/* Validate length. */
393+
if ((md_len == 0) || (md_len > CONFIG_BLE_SCAN_MANUFACTURER_DATA_MAX_LEN)) {
394+
return NRF_ERROR_DATA_SIZE;
395+
}
396+
397+
/* Validate md_data. */
398+
if (md_data == NULL) {
399+
return NRF_ERROR_NULL;
400+
}
401+
402+
/* Check for duplicated filter. */
403+
for (uint8_t i = 0; i < *counter; i++) {
404+
if ((md_filter->manufacturer_data[i].data_len == md_len) &&
405+
(memcmp(md_filter->manufacturer_data[i].data, md_data, md_len) == 0)) {
406+
return NRF_SUCCESS;
407+
}
408+
}
409+
410+
/* Check for free slot. */
411+
if (*counter >= CONFIG_BLE_SCAN_MANUFACTURER_DATA_COUNT) {
412+
return NRF_ERROR_NO_MEM;
413+
}
414+
415+
/* Add manufacturer data to filter. */
416+
memcpy(md_filter->manufacturer_data[*counter].data, md_data, md_len);
417+
md_filter->manufacturer_data[*counter].data_len = md_len;
418+
(*counter)++;
419+
420+
LOG_DBG("Added manufacturer data filter");
421+
LOG_HEXDUMP_DBG(md_data, md_len, "Manufacturer data");
422+
423+
return NRF_SUCCESS;
424+
}
425+
#endif /* CONFIG_BLE_SCAN_MANUFACTURER_DATA_COUNT */
426+
365427
uint32_t ble_scan_filter_add(struct ble_scan *scan, uint8_t type,
366428
const struct ble_scan_filter_data *data)
367429
{
@@ -400,6 +462,12 @@ uint32_t ble_scan_filter_add(struct ble_scan *scan, uint8_t type,
400462
}
401463
#endif
402464

465+
#if (CONFIG_BLE_SCAN_MANUFACTURER_DATA_COUNT > 0)
466+
case BLE_SCAN_MANUFACTURER_DATA_FILTER: {
467+
return manufacturer_data_filter_add(scan, data);
468+
}
469+
#endif
470+
403471
default:
404472
return NRF_ERROR_INVALID_PARAM;
405473
}
@@ -444,6 +512,14 @@ uint32_t ble_scan_all_filter_remove(struct ble_scan *scan)
444512
appearance_filter->appearance_cnt = 0;
445513
#endif
446514

515+
#if (CONFIG_BLE_SCAN_MANUFACTURER_DATA_COUNT > 0)
516+
struct ble_scan_manufacturer_data_filter *md_filter =
517+
&scan->scan_filters.manufacturer_data_filter;
518+
519+
memset(md_filter->manufacturer_data, 0, sizeof(md_filter->manufacturer_data));
520+
md_filter->manufacturer_data_cnt = 0;
521+
#endif
522+
447523
return NRF_SUCCESS;
448524
}
449525

@@ -461,7 +537,8 @@ uint32_t ble_scan_filters_enable(struct ble_scan *scan, uint8_t mode, bool match
461537
(!(mode & BLE_SCAN_NAME_FILTER)) &&
462538
(!(mode & BLE_SCAN_UUID_FILTER)) &&
463539
(!(mode & BLE_SCAN_SHORT_NAME_FILTER)) &&
464-
(!(mode & BLE_SCAN_APPEARANCE_FILTER))) {
540+
(!(mode & BLE_SCAN_APPEARANCE_FILTER)) &&
541+
(!(mode & BLE_SCAN_MANUFACTURER_DATA_FILTER))) {
465542
return NRF_ERROR_INVALID_PARAM;
466543
}
467544

@@ -502,6 +579,12 @@ uint32_t ble_scan_filters_enable(struct ble_scan *scan, uint8_t mode, bool match
502579
}
503580
#endif
504581

582+
#if (CONFIG_BLE_SCAN_MANUFACTURER_DATA_COUNT > 0)
583+
if (mode & BLE_SCAN_MANUFACTURER_DATA_FILTER) {
584+
filters->manufacturer_data_filter.manufacturer_data_filter_enabled = true;
585+
}
586+
#endif
587+
505588
/* Select the filter mode. */
506589
filters->all_filters_mode = match_all;
507590

@@ -539,6 +622,10 @@ uint32_t ble_scan_filters_disable(struct ble_scan *scan)
539622
filters->appearance_filter.appearance_filter_enabled = false;
540623
#endif
541624

625+
#if (CONFIG_BLE_SCAN_MANUFACTURER_DATA_COUNT > 0)
626+
filters->manufacturer_data_filter.manufacturer_data_filter_enabled = false;
627+
#endif
628+
542629
return NRF_SUCCESS;
543630
}
544631

@@ -771,6 +858,21 @@ static void ble_scan_on_adv_report(struct ble_scan *scan,
771858
}
772859
#endif /* CONFIG_BLE_SCAN_APPEARANCE_COUNT */
773860

861+
#if (CONFIG_BLE_SCAN_MANUFACTURER_DATA_COUNT > 0)
862+
/* Check the manufacturer data filter. */
863+
if (scan->scan_filters.manufacturer_data_filter.manufacturer_data_filter_enabled) {
864+
filter_cnt++;
865+
if (adv_manufacturer_data_compare(scan, adv_report->data.p_data,
866+
adv_report->data.len) ||
867+
(active_match_all &&
868+
adv_manufacturer_data_compare(scan, adv_data, adv_data_len))) {
869+
filter_match_cnt++;
870+
871+
scan_evt.filter_match.filter_match.manufacturer_data_filter_match = true;
872+
}
873+
}
874+
#endif /* CONFIG_BLE_SCAN_MANUFACTURER_DATA_COUNT */
875+
774876
/* In the multifilter mode, the number of the active filters must equal the number of the
775877
* filters matched to generate the notification.
776878
*/

tests/unit/lib/bluetooth/ble_scan/prj.conf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ CONFIG_UNITY=y
33
CONFIG_BLE_SCAN_BUFFER_SIZE=31
44
CONFIG_BLE_SCAN_NAME_MAX_LEN=32
55
CONFIG_BLE_SCAN_SHORT_NAME_MAX_LEN=32
6+
CONFIG_BLE_SCAN_MANUFACTURER_DATA_MAX_LEN=32
67
CONFIG_BLE_SCAN_NAME_COUNT=1
78
CONFIG_BLE_SCAN_APPEARANCE_COUNT=1
89
CONFIG_BLE_SCAN_ADDRESS_COUNT=1
910
CONFIG_BLE_SCAN_SHORT_NAME_COUNT=2
1011
CONFIG_BLE_SCAN_UUID_COUNT=1
12+
CONFIG_BLE_SCAN_MANUFACTURER_DATA_COUNT=2
1113
CONFIG_BLE_SCAN_INTERVAL=160
1214
CONFIG_BLE_SCAN_DURATION=0
1315
CONFIG_BLE_SCAN_WINDOW=80

0 commit comments

Comments
 (0)