Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve support for extended advertising and add missing setters for advertising parameters #813

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions libraries/Bluefruit52Lib/library.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name=Adafruit Bluefruit nRF52 Libraries
version=0.21.0
author=Adafruit
version=0.21.1
author=JensB
maintainer=Adafruit <[email protected]>
sentence=Arduino library for nRF52-based Adafruit Bluefruit LE modules
paragraph=Arduino library for nRF52-based Adafruit Bluefruit LE modules
Expand Down
132 changes: 109 additions & 23 deletions libraries/Bluefruit52Lib/src/BLEAdvertising.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,17 @@
*------------------------------------------------------------------*/
BLEAdvertisingData::BLEAdvertisingData(void)
{
_count = 0;
arrclr(_data);
clearData();
}

void BLEAdvertisingData::setMaxLen(uint8_t max_len)
{
_max_len = max_len;
}

bool BLEAdvertisingData::addData(uint8_t type, const void* data, uint8_t len)
{
VERIFY( _count + len + 2 <= BLE_GAP_ADV_SET_DATA_SIZE_MAX );
VERIFY( _count + len + 2 <= _max_len );

uint8_t* adv_data = &_data[_count];

Expand Down Expand Up @@ -183,7 +187,7 @@ bool BLEAdvertisingData::addName(void)
uint8_t len = Bluefruit.getName(name, sizeof(name));

// not enough for full name, chop it
if (_count + len + 2 > BLE_GAP_ADV_SET_DATA_SIZE_MAX)
if (_count + len + 2 > _max_len)
{
type = BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME;
len = BLE_GAP_ADV_SET_DATA_SIZE_MAX - (_count+2);
Expand Down Expand Up @@ -231,7 +235,7 @@ uint8_t* BLEAdvertisingData::getData(void)

bool BLEAdvertisingData::setData(uint8_t const * data, uint8_t count)
{
VERIFY( data && (count <= BLE_GAP_ADV_SET_DATA_SIZE_MAX) );
VERIFY( data && (count <= _max_len) );

memcpy(_data, data, count);
_count = count;
Expand All @@ -243,6 +247,7 @@ void BLEAdvertisingData::clearData(void)
{
_count = 0;
arrclr(_data);
_max_len = BLE_GAP_ADV_SET_DATA_SIZE_MAX;
}

/*------------------------------------------------------------------*/
Expand Down Expand Up @@ -275,6 +280,14 @@ void BLEAdvertising::setFastTimeout(uint16_t sec)
void BLEAdvertising::setType(uint8_t adv_type)
{
_type = adv_type;
if (isExtended())
{
setMaxLen(BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_MAX_SUPPORTED);
}
else
{
setMaxLen(BLE_GAP_ADV_SET_DATA_SIZE_MAX);
}
}

/**
Expand All @@ -296,6 +309,22 @@ void BLEAdvertising::setIntervalMS(uint16_t fast, uint16_t slow)
setInterval(MS1000TO625(fast), MS1000TO625(slow));
}

void BLEAdvertising::setMaxEvents(uint8_t maxEvents)
{
_max_events = maxEvents;
}

void BLEAdvertising::setFilter(uint8_t filter)
{
_filter = filter;
}

void BLEAdvertising::setPhy(uint8_t phy)
{
_primary_phy = phy;
_secondary_phy = phy;
}

/**
* Get current active interval
* @return Either slow or fast interval in unit of 0.625 ms
Expand Down Expand Up @@ -324,6 +353,42 @@ bool BLEAdvertising::isRunning(void)
return _runnning;
}

bool BLEAdvertising::isScannable(void)
{
return _type == BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED
|| _type == BLE_GAP_ADV_TYPE_NONCONNECTABLE_SCANNABLE_UNDIRECTED
|| _type == BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_SCANNABLE_UNDIRECTED
|| _type == BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_SCANNABLE_DIRECTED;
}

bool BLEAdvertising::isConnectable(void)
{
return _type == BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED
|| _type == BLE_GAP_ADV_TYPE_CONNECTABLE_NONSCANNABLE_DIRECTED_HIGH_DUTY_CYCLE
|| _type == BLE_GAP_ADV_TYPE_CONNECTABLE_NONSCANNABLE_DIRECTED
|| _type == BLE_GAP_ADV_TYPE_EXTENDED_CONNECTABLE_NONSCANNABLE_UNDIRECTED
|| _type == BLE_GAP_ADV_TYPE_EXTENDED_CONNECTABLE_NONSCANNABLE_DIRECTED;
}

bool BLEAdvertising::isDirected(void)
{
return _type == BLE_GAP_ADV_TYPE_CONNECTABLE_NONSCANNABLE_DIRECTED_HIGH_DUTY_CYCLE
|| _type == BLE_GAP_ADV_TYPE_CONNECTABLE_NONSCANNABLE_DIRECTED
|| _type == BLE_GAP_ADV_TYPE_EXTENDED_CONNECTABLE_NONSCANNABLE_DIRECTED
|| _type == BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_SCANNABLE_DIRECTED
|| _type == BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_NONSCANNABLE_DIRECTED;
}

bool BLEAdvertising::isExtended(void)
{
return _type == BLE_GAP_ADV_TYPE_EXTENDED_CONNECTABLE_NONSCANNABLE_UNDIRECTED
|| _type == BLE_GAP_ADV_TYPE_EXTENDED_CONNECTABLE_NONSCANNABLE_DIRECTED
|| _type == BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_SCANNABLE_UNDIRECTED
|| _type == BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_SCANNABLE_DIRECTED
|| _type == BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED
|| _type == BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_NONSCANNABLE_DIRECTED;
}

bool BLEAdvertising::setBeacon(BLEBeacon& beacon)
{
return beacon.start(*this);
Expand All @@ -348,32 +413,41 @@ bool BLEAdvertising::_start(uint16_t interval, uint16_t timeout)
.interval = interval , // advertising interval (in units of 0.625 ms)
.duration = (uint16_t) (timeout*100) , // in 10-ms unit

.max_adv_evts = 0 , // TODO can be used for fast/slow mode
.channel_mask = { 0, 0, 0, 0, 0 } , // 40 channel, set 1 to disable
.filter_policy = BLE_GAP_ADV_FP_ANY ,
.max_adv_evts = _max_events , // can be used for fast/slow mode
.channel_mask = { 0, 0, 0, 0, 0 } , // 40 channel, set 1 to disable, e.g. { 0, 0, 0, 0, 0xA0 } for not primary 37 and 38
.filter_policy = _filter ,

.primary_phy = BLE_GAP_PHY_AUTO , // 1 Mbps will be used
.secondary_phy = BLE_GAP_PHY_AUTO , // 1 Mbps will be used
.primary_phy = (isExtended() ? _primary_phy : (uint8_t)BLE_GAP_PHY_AUTO) ,
.secondary_phy = _secondary_phy ,
// , .set_id, .scan_req_notification
};

switch(_type) {
case BLE_GAP_ADV_TYPE_CONNECTABLE_NONSCANNABLE_DIRECTED_HIGH_DUTY_CYCLE:
case BLE_GAP_ADV_TYPE_CONNECTABLE_NONSCANNABLE_DIRECTED:
case BLE_GAP_ADV_TYPE_EXTENDED_CONNECTABLE_NONSCANNABLE_DIRECTED:
case BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_SCANNABLE_DIRECTED:
case BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_NONSCANNABLE_DIRECTED:
adv_para.p_peer_addr = &_peer_addr;
break;

default: break;
}

if (isDirected()) {
adv_para.p_peer_addr = &_peer_addr;
}

// gap_adv long-live is required by SD v6
static ble_gap_adv_data_t gap_adv = {
.adv_data = { .p_data = _data, .len = _count },
.scan_rsp_data = { .p_data = Bluefruit.ScanResponse.getData(), .len = Bluefruit.ScanResponse.count() }
};

// no advertising data supported?
// https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.s140.api.v7.3.0/group___b_l_e___g_a_p___a_d_v___t_y_p_e_s.html
if ( _type == BLE_GAP_ADV_TYPE_CONNECTABLE_NONSCANNABLE_DIRECTED
|| _type == BLE_GAP_ADV_TYPE_CONNECTABLE_NONSCANNABLE_DIRECTED_HIGH_DUTY_CYCLE
|| _type == BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_SCANNABLE_UNDIRECTED
|| _type == BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_SCANNABLE_DIRECTED )
{
gap_adv.adv_data = { .p_data = nullptr, .len = 0 };
}

// no scan response data required?
if (!isScannable())
{
gap_adv.scan_rsp_data = { .p_data = nullptr, .len = 0 };
}

VERIFY_STATUS( sd_ble_gap_adv_set_configure(&_hdl, &gap_adv, &adv_para), false );
VERIFY_STATUS( sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, _hdl, Bluefruit.getTxPower() ), false );
VERIFY_STATUS( sd_ble_gap_adv_start(_hdl, CONN_CFG_PERIPHERAL), false );
Expand Down Expand Up @@ -473,9 +547,21 @@ void BLEAdvertising::_eventHandler(ble_evt_t* evt)
if (_stop_cb) ada_callback(NULL, 0, _stop_cb);
}
}
}else
{
if (evt->evt.gap_evt.params.adv_set_terminated.reason == BLE_GAP_EVT_ADV_SET_TERMINATED_REASON_LIMIT_REACHED)
{
_runnning = false;

// Stop advertising
Bluefruit._stopConnLed(); // stop blinking

// invoke stop callback
if (_stop_cb) ada_callback(NULL, 0, _stop_cb);
}
}
break;

default: break;
}
}
}
19 changes: 18 additions & 1 deletion libraries/Bluefruit52Lib/src/BLEAdvertising.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,16 @@ class Advertisable
class BLEAdvertisingData
{
protected:
uint8_t _data[BLE_GAP_ADV_SET_DATA_SIZE_MAX];
uint8_t _max_len = BLE_GAP_ADV_SET_DATA_SIZE_MAX;
uint8_t _data[BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_CONNECTABLE_MAX_SUPPORTED];
uint8_t _count;

public:
BLEAdvertisingData(void);

// @param max_len must be set before adding data, defaults to BLE_GAP_ADV_SET_DATA_SIZE_MAX
void setMaxLen(uint8_t max_len);

/*------------- Adv Data -------------*/
bool addData(uint8_t type, const void* data, uint8_t len);
bool addFlags(uint8_t flags);
Expand Down Expand Up @@ -120,6 +124,7 @@ class BLEAdvertising : public BLEAdvertisingData

BLEAdvertising(void);

// must be set as first property after clear for extended advertising
void setType(uint8_t adv_type);
void setFastTimeout(uint16_t sec);

Expand All @@ -129,6 +134,10 @@ class BLEAdvertising : public BLEAdvertisingData
void setInterval (uint16_t fast, uint16_t slow);
void setIntervalMS(uint16_t fast, uint16_t slow);

void setMaxEvents(uint8_t maxEvents);
void setFilter(uint8_t filter);
void setPhy(uint8_t phy);

uint16_t getInterval(void);

bool setBeacon(BLEBeacon& beacon);
Expand All @@ -138,6 +147,10 @@ class BLEAdvertising : public BLEAdvertisingData
void setPeerAddress(const ble_gap_addr_t& peer_addr);

bool isRunning(void);
bool isScannable(void);
bool isConnectable(void);
bool isDirected(void);
bool isExtended(void);

void restartOnDisconnect(bool enable);
bool start(uint16_t timeout = 0);
Expand All @@ -153,6 +166,10 @@ class BLEAdvertising : public BLEAdvertisingData
private:
uint8_t _hdl;
uint8_t _type;
uint8_t _max_events = 0; // initially time limited
uint8_t _filter = BLE_GAP_ADV_FP_ANY;
uint8_t _primary_phy = BLE_GAP_PHY_AUTO;
uint8_t _secondary_phy = BLE_GAP_PHY_AUTO;
bool _start_if_disconnect;
bool _runnning;
ble_gap_addr_t _peer_addr; //! Target address for an ADV_DIRECT_IND advertisement
Expand Down
Loading