Skip to content

Commit e3f6b95

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 e3f6b95

6 files changed

Lines changed: 362 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: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,67 @@ 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+
if (!md_data) {
398+
return NRF_ERROR_NULL;
399+
}
400+
401+
/* Check for duplicated filter. */
402+
for (uint8_t i = 0; i < *counter; i++) {
403+
if ((md_filter->manufacturer_data[i].data_len == md_len) &&
404+
(memcmp(md_filter->manufacturer_data[i].data, md_data, md_len) == 0)) {
405+
return NRF_SUCCESS;
406+
}
407+
}
408+
409+
/* Check for free slot. */
410+
if (*counter >= CONFIG_BLE_SCAN_MANUFACTURER_DATA_COUNT) {
411+
return NRF_ERROR_NO_MEM;
412+
}
413+
414+
/* Add manufacturer data to filter. */
415+
memcpy(md_filter->manufacturer_data[*counter].data, md_data, md_len);
416+
md_filter->manufacturer_data[*counter].data_len = md_len;
417+
(*counter)++;
418+
419+
LOG_DBG("Added manufacturer data filter");
420+
LOG_HEXDUMP_DBG(md_data, md_len, "Manufacturer data");
421+
422+
return NRF_SUCCESS;
423+
}
424+
#endif /* CONFIG_BLE_SCAN_MANUFACTURER_DATA_COUNT */
425+
365426
uint32_t ble_scan_filter_add(struct ble_scan *scan, uint8_t type,
366427
const struct ble_scan_filter_data *data)
367428
{
@@ -400,6 +461,12 @@ uint32_t ble_scan_filter_add(struct ble_scan *scan, uint8_t type,
400461
}
401462
#endif
402463

464+
#if (CONFIG_BLE_SCAN_MANUFACTURER_DATA_COUNT > 0)
465+
case BLE_SCAN_MANUFACTURER_DATA_FILTER: {
466+
return manufacturer_data_filter_add(scan, data);
467+
}
468+
#endif
469+
403470
default:
404471
return NRF_ERROR_INVALID_PARAM;
405472
}
@@ -444,6 +511,14 @@ uint32_t ble_scan_all_filter_remove(struct ble_scan *scan)
444511
appearance_filter->appearance_cnt = 0;
445512
#endif
446513

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

@@ -461,7 +536,8 @@ uint32_t ble_scan_filters_enable(struct ble_scan *scan, uint8_t mode, bool match
461536
(!(mode & BLE_SCAN_NAME_FILTER)) &&
462537
(!(mode & BLE_SCAN_UUID_FILTER)) &&
463538
(!(mode & BLE_SCAN_SHORT_NAME_FILTER)) &&
464-
(!(mode & BLE_SCAN_APPEARANCE_FILTER))) {
539+
(!(mode & BLE_SCAN_APPEARANCE_FILTER)) &&
540+
(!(mode & BLE_SCAN_MANUFACTURER_DATA_FILTER))) {
465541
return NRF_ERROR_INVALID_PARAM;
466542
}
467543

@@ -502,6 +578,12 @@ uint32_t ble_scan_filters_enable(struct ble_scan *scan, uint8_t mode, bool match
502578
}
503579
#endif
504580

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

@@ -539,6 +621,10 @@ uint32_t ble_scan_filters_disable(struct ble_scan *scan)
539621
filters->appearance_filter.appearance_filter_enabled = false;
540622
#endif
541623

624+
#if (CONFIG_BLE_SCAN_MANUFACTURER_DATA_COUNT > 0)
625+
filters->manufacturer_data_filter.manufacturer_data_filter_enabled = false;
626+
#endif
627+
542628
return NRF_SUCCESS;
543629
}
544630

@@ -771,6 +857,21 @@ static void ble_scan_on_adv_report(struct ble_scan *scan,
771857
}
772858
#endif /* CONFIG_BLE_SCAN_APPEARANCE_COUNT */
773859

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

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=1
1113
CONFIG_BLE_SCAN_INTERVAL=160
1214
CONFIG_BLE_SCAN_DURATION=0
1315
CONFIG_BLE_SCAN_WINDOW=80

0 commit comments

Comments
 (0)