From f4a18802a50acaafb091691b0eff207bc74942ec Mon Sep 17 00:00:00 2001 From: lianggao Date: Thu, 23 Feb 2017 13:55:34 +0800 Subject: [PATCH] Jira 802, BLE Central scan() to filter Peripheral adv, git #369 New feature: - Request from Arduino to make our Central BLE library to scan Peripheral similar to an Apple device. - When filter is set, advertisement from a Peripheral will only show up once (until scan is stop and start again) with the available() call. Otherwise, a Peripheral will appear as often as the Central can detect its advertisement. - Unlike an Apple device, the 101 operates under memory constraints. Thus, the maximum number of filter entries is limited to 20. In other words, if ther are more than 20 Peripherals, the filter will NOT be able to filter out all the advertisement all the time. A Peripherla WILL show up multiple times when available() is called. Code mods: 1. BLECommon.h: - Definition of the filter entries size. 2. BLEDeviceManager.cpp: - Peripheral filtering initialization at startScanningWithDuplicates(). - Added deviceInDuplicateFilterBuffer() for search a newly detected Peripheral against a recorded list of devices. - Added updateDuplicateFilter() to record any newly detected Peripoheral. - At available(), check for duplicated Peripheral prior to return it to caller. Discard any reported Peripheral. Record any newly detected one prior to return it to caller. --- libraries/CurieBLE/src/BLECommon.h | 1 + .../src/internal/BLEDeviceManager.cpp | 57 ++++++++++++++++++- .../CurieBLE/src/internal/BLEDeviceManager.h | 6 ++ 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/libraries/CurieBLE/src/BLECommon.h b/libraries/CurieBLE/src/BLECommon.h index 76e6b804..37ac49df 100644 --- a/libraries/CurieBLE/src/BLECommon.h +++ b/libraries/CurieBLE/src/BLECommon.h @@ -103,6 +103,7 @@ typedef ble_status_t BleStatus; #define BLE_MAX_CONN_CFG 2 #define BLE_MAX_ADV_BUFFER_CFG 3 +#define BLE_MAX_ADV_FILTER_SIZE_CFG 20 typedef bool (*ble_advertise_handle_cb_t)(uint8_t type, const uint8_t *dataPtr, uint8_t data_len, const bt_addr_le_t *addrPtr); diff --git a/libraries/CurieBLE/src/internal/BLEDeviceManager.cpp b/libraries/CurieBLE/src/internal/BLEDeviceManager.cpp index b3e74278..643e6b97 100644 --- a/libraries/CurieBLE/src/internal/BLEDeviceManager.cpp +++ b/libraries/CurieBLE/src/internal/BLEDeviceManager.cpp @@ -47,7 +47,10 @@ BLEDeviceManager::BLEDeviceManager(): _local_name(""), _state(BLE_PERIPH_STATE_NOT_READY), _local_ble(NULL), - _peer_peripheral_index(0) + _peer_peripheral_index(0), + _duplicate_filter_header(0), + _duplicate_filter_tail(0), + _adv_duplicate_filter_enabled(false) { memset(&_local_bda, 0, sizeof(_local_bda)); memset(&_wait_for_connect_peripheral, 0, sizeof(_wait_for_connect_peripheral)); @@ -530,7 +533,8 @@ BLEDevice BLEDeviceManager::peripheral() bool BLEDeviceManager::startScanning() { - _scan_param.filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_ENABLE;//BT_HCI_LE_SCAN_FILTER_DUP_DISABLE; + _adv_duplicate_filter_enabled = false; + _scan_param.filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_ENABLE; int err = bt_le_scan_start(&_scan_param, ble_central_device_found); if (err) { @@ -542,6 +546,10 @@ bool BLEDeviceManager::startScanning() bool BLEDeviceManager::startScanningWithDuplicates() { + _adv_duplicate_filter_enabled = true; + memset(_peer_duplicate_address_buffer, 0, sizeof(_peer_duplicate_address_buffer)); + _duplicate_filter_header = _duplicate_filter_tail = 0; + _scan_param.filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_ENABLE; int err = bt_le_scan_start(&_scan_param, ble_central_device_found); if (err) @@ -549,7 +557,7 @@ bool BLEDeviceManager::startScanningWithDuplicates() pr_info(LOG_MODULE_BLE, "Scanning failed to start (err %d)\n", err); return false; } - return false; + return true; } bool BLEDeviceManager::stopScanning() @@ -1164,6 +1172,38 @@ bool BLEDeviceManager::advertiseDataProc(uint8_t type, return false; } +bool BLEDeviceManager::deviceInDuplicateFilterBuffer(const bt_addr_le_t* addr) +{ + bool retVal = false; + for (uint8_t i = 0; + i < (sizeof(_peer_duplicate_address_buffer) / sizeof(bt_addr_le_t)); + i++) + { + if (0 == bt_addr_le_cmp(addr, &_peer_duplicate_address_buffer[i])) + { + retVal = true; + break; + } + } + return retVal; +} + +void BLEDeviceManager::updateDuplicateFilter(const bt_addr_le_t* addr) +{ + uint8_t i = (_duplicate_filter_header + 1) % (ARRAY_SIZE(_peer_duplicate_address_buffer)); + if (deviceInDuplicateFilterBuffer(addr)) + { + return; + } + bt_addr_le_copy(&_peer_duplicate_address_buffer[_duplicate_filter_header], + addr); + if (i == _duplicate_filter_tail) + { + _duplicate_filter_tail = (_duplicate_filter_tail + 1) % (ARRAY_SIZE(_peer_duplicate_address_buffer)); + } + _duplicate_filter_header = i; +} + BLEDevice BLEDeviceManager::available() { BLEDevice tempdevice; @@ -1179,6 +1219,13 @@ BLEDevice BLEDeviceManager::available() temp = &_peer_adv_buffer[i]; if ((timestamp_delta <= 2000) && (max_delta < timestamp_delta)) { + // Eable the duplicate filter + if (_adv_duplicate_filter_enabled && + true == deviceInDuplicateFilterBuffer(temp)) + { + _peer_adv_mill[i] -= 2000; // Invalid the item + continue; + } max_delta = timestamp_delta; index = i; } @@ -1198,6 +1245,10 @@ BLEDevice BLEDeviceManager::available() pr_debug(LOG_MODULE_BLE, "%s-%d:Con addr-%s", __FUNCTION__, __LINE__, BLEUtils::macAddressBT2String(*temp).c_str()); _peer_adv_mill[index] -= 2000; // Set it as expired + if (_adv_duplicate_filter_enabled) + { + updateDuplicateFilter(temp); + } } } return tempdevice; diff --git a/libraries/CurieBLE/src/internal/BLEDeviceManager.h b/libraries/CurieBLE/src/internal/BLEDeviceManager.h index 2e9d93b0..e09bfe6c 100644 --- a/libraries/CurieBLE/src/internal/BLEDeviceManager.h +++ b/libraries/CurieBLE/src/internal/BLEDeviceManager.h @@ -362,6 +362,8 @@ class BLEDeviceManager const uint8_t* &adv_data, uint8_t &adv_len) const; bool disconnectSingle(const bt_addr_le_t *peer); + void updateDuplicateFilter(const bt_addr_le_t* addr); + bool deviceInDuplicateFilterBuffer(const bt_addr_le_t* addr); private: uint16_t _min_conn_interval; @@ -432,6 +434,10 @@ class BLEDeviceManager uint8_t _peer_peripheral_adv_data[BLE_MAX_CONN_CFG][BLE_MAX_ADV_SIZE]; uint8_t _peer_peripheral_adv_data_len[BLE_MAX_CONN_CFG]; uint8_t _peer_peripheral_adv_rssi[BLE_MAX_CONN_CFG]; + bt_addr_le_t _peer_duplicate_address_buffer[BLE_MAX_ADV_FILTER_SIZE_CFG]; + uint8_t _duplicate_filter_header; + uint8_t _duplicate_filter_tail; + bool _adv_duplicate_filter_enabled; BLEDeviceEventHandler _device_events[BLEDeviceLastEvent]; };