Skip to content

Commit 356109f

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 356109f

6 files changed

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

467+
#if (CONFIG_BLE_SCAN_MANUFACTURER_DATA_COUNT > 0)
468+
case BLE_SCAN_MANUFACTURER_DATA_FILTER: {
469+
return manufacturer_data_filter_add(scan, data);
470+
}
471+
#endif
472+
403473
default:
404474
return NRF_ERROR_INVALID_PARAM;
405475
}
@@ -444,6 +514,14 @@ uint32_t ble_scan_all_filter_remove(struct ble_scan *scan)
444514
appearance_filter->appearance_cnt = 0;
445515
#endif
446516

517+
#if (CONFIG_BLE_SCAN_MANUFACTURER_DATA_COUNT > 0)
518+
struct ble_scan_manufacturer_data_filter *md_filter =
519+
&scan->scan_filters.manufacturer_data_filter;
520+
521+
memset(md_filter->manufacturer_data, 0, sizeof(md_filter->manufacturer_data));
522+
md_filter->manufacturer_data_cnt = 0;
523+
#endif
524+
447525
return NRF_SUCCESS;
448526
}
449527

@@ -461,7 +539,8 @@ uint32_t ble_scan_filters_enable(struct ble_scan *scan, uint8_t mode, bool match
461539
(!(mode & BLE_SCAN_NAME_FILTER)) &&
462540
(!(mode & BLE_SCAN_UUID_FILTER)) &&
463541
(!(mode & BLE_SCAN_SHORT_NAME_FILTER)) &&
464-
(!(mode & BLE_SCAN_APPEARANCE_FILTER))) {
542+
(!(mode & BLE_SCAN_APPEARANCE_FILTER)) &&
543+
(!(mode & BLE_SCAN_MANUFACTURER_DATA_FILTER))) {
465544
return NRF_ERROR_INVALID_PARAM;
466545
}
467546

@@ -502,6 +581,12 @@ uint32_t ble_scan_filters_enable(struct ble_scan *scan, uint8_t mode, bool match
502581
}
503582
#endif
504583

584+
#if (CONFIG_BLE_SCAN_MANUFACTURER_DATA_COUNT > 0)
585+
if (mode & BLE_SCAN_MANUFACTURER_DATA_FILTER) {
586+
filters->manufacturer_data_filter.manufacturer_data_filter_enabled = true;
587+
}
588+
#endif
589+
505590
/* Select the filter mode. */
506591
filters->all_filters_mode = match_all;
507592

@@ -539,6 +624,10 @@ uint32_t ble_scan_filters_disable(struct ble_scan *scan)
539624
filters->appearance_filter.appearance_filter_enabled = false;
540625
#endif
541626

627+
#if (CONFIG_BLE_SCAN_MANUFACTURER_DATA_COUNT > 0)
628+
filters->manufacturer_data_filter.manufacturer_data_filter_enabled = false;
629+
#endif
630+
542631
return NRF_SUCCESS;
543632
}
544633

@@ -771,6 +860,21 @@ static void ble_scan_on_adv_report(struct ble_scan *scan,
771860
}
772861
#endif /* CONFIG_BLE_SCAN_APPEARANCE_COUNT */
773862

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

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)