Skip to content

Commit 5380769

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 69d121d commit 5380769

6 files changed

Lines changed: 458 additions & 9 deletions

File tree

doc/nrf-bm/release_notes/release_notes_changelog.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,14 @@ Libraries
7878

7979
* 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.
8080

81+
* :ref:`lib_ble_scan` library:
82+
83+
* Added:
84+
85+
* The :c:struct:`ble_scan_filter_data` structure as input to the :c:func:`ble_scan_filter_add` function.
86+
* Support for filtering by manufacturer-specific data using the :c:macro:`BLE_SCAN_MANUFACTURER_DATA_FILTER` filter type.
87+
* 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.
88+
8189
Bluetooth LE Services
8290
---------------------
8391

include/bm/bluetooth/ble_scan.h

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

112114
/**
@@ -137,6 +139,13 @@ struct ble_scan_filter_data {
137139
/** Minimum length of the short name to be matched. */
138140
uint8_t short_name_min_len;
139141
} short_name_filter;
142+
/** Manufacturer filter data */
143+
struct {
144+
/** Pointer to the manufacturer data. */
145+
uint8_t *data;
146+
/** Manufacturer data length. */
147+
uint8_t data_len;
148+
} manufacturer_data_filter;
140149
};
141150
};
142151

@@ -154,6 +163,8 @@ struct ble_scan_filter_match {
154163
uint8_t appearance_filter_match: 1;
155164
/** Set to 1 if short name filter is matched. */
156165
uint8_t short_name_filter_match: 1;
166+
/** Set to 1 if manufacturer data filter is matched. */
167+
uint8_t manufacturer_data_filter_match: 1;
157168
};
158169

159170
/**
@@ -292,6 +303,22 @@ struct ble_scan_appearance_filter {
292303
bool appearance_filter_enabled;
293304
};
294305

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