generic advertising

pull/8738/head
paul-szczepanek-arm 2018-11-07 15:54:20 +00:00 committed by Vincent Coubard
parent f35ebcc900
commit 6ca5041f53
5 changed files with 298 additions and 20 deletions

View File

@ -1017,6 +1017,7 @@ public:
typedef uint8_t AdvHandle_t; typedef uint8_t AdvHandle_t;
static const AdvHandle_t LEGACY_ADVERTISING_HANDLE = 0x00; static const AdvHandle_t LEGACY_ADVERTISING_HANDLE = 0x00;
static const AdvHandle_t INVALID_ADVERTISING_HANDLE = 0xFF;
struct AdvReportOptionalInformation { struct AdvReportOptionalInformation {
PeerAddressType_t directAddressType; PeerAddressType_t directAddressType;

View File

@ -537,7 +537,8 @@ public:
GapAdvertisingData(void) : GapAdvertisingData(void) :
_payload(), _payload(),
_payloadLen(0), _payloadLen(0),
_appearance(GENERIC_TAG) { _appearance(GENERIC_TAG),
_minimiseFragmentation(false) {
} }
/** /**
@ -724,6 +725,14 @@ public:
return NULL; return NULL;
} }
void setMinimiseFragmentation(bool enable = true) {
_minimiseFragmentation = enable;
}
bool getMinimiseFragmentation() {
return _minimiseFragmentation;
}
private: private:
/** /**
* Append advertising data based on the specified type. * Append advertising data based on the specified type.
@ -913,6 +922,8 @@ private:
* Appearance value. * Appearance value.
*/ */
uint16_t _appearance; uint16_t _appearance;
bool _minimiseFragmentation;
}; };
/** /**

View File

@ -285,7 +285,7 @@ class GapExtendedAdvertisingParams {
* *
* @param[in] newAdvType The new advertising type. * @param[in] newAdvType The new advertising type.
*/ */
void setAdvertisingType(ble::advertising_type_t newAdvType) { void setType(ble::advertising_type_t newAdvType) {
_advType = newAdvType; _advType = newAdvType;
} }
@ -294,7 +294,7 @@ class GapExtendedAdvertisingParams {
* *
* @return Advertising type. * @return Advertising type.
*/ */
ble::advertising_type_t setAdvertisingType() { ble::advertising_type_t getType() {
return _advType; return _advType;
} }
@ -308,7 +308,7 @@ class GapExtendedAdvertisingParams {
_anonymous = enable; _anonymous = enable;
} }
ble_error_t getPrimaryAdvertisingInterval( ble_error_t getPrimaryInterval(
uint32_t *min /* ms */, uint32_t *min /* ms */,
uint32_t *max /* ms */ uint32_t *max /* ms */
) { ) {
@ -320,7 +320,7 @@ class GapExtendedAdvertisingParams {
return BLE_ERROR_NONE; return BLE_ERROR_NONE;
} }
void setPrimaryAdvertisingInterval( void setPrimaryInterval(
uint32_t min /* ms */, uint32_t min /* ms */,
uint32_t max /* ms */ uint32_t max /* ms */
) { ) {
@ -328,7 +328,7 @@ class GapExtendedAdvertisingParams {
_maxInterval = max; _maxInterval = max;
} }
ble_error_t getPrimaryAdvertisingChannels( ble_error_t getPrimaryChannels(
bool *channel37, bool *channel37,
bool *channel38, bool *channel38,
bool *channel39 bool *channel39
@ -342,7 +342,7 @@ class GapExtendedAdvertisingParams {
return BLE_ERROR_NONE; return BLE_ERROR_NONE;
} }
void setPrimaryAdvertisingChannels( void setPrimaryChannels(
bool channel37, bool channel37,
bool channel38, bool channel38,
bool channel39 bool channel39
@ -382,27 +382,27 @@ class GapExtendedAdvertisingParams {
_peerAddressType = addressType; _peerAddressType = addressType;
}; };
ble::advertising_policy_mode_t getAdvertisingPolicyMode() { ble::advertising_policy_mode_t getPolicyMode() {
return _policy; return _policy;
} }
void setAdvertisingPolicyMode( void setPolicyMode(
ble::advertising_policy_mode_t mode ble::advertising_policy_mode_t mode
) { ) {
_policy = mode; _policy = mode;
} }
int8_t getAdvertisingTxPower() { int8_t getTxPower() {
return _txPower; return _txPower;
} }
void setAdvertisingTxPower( void setTxPower(
int8_t txPower int8_t txPower
) { ) {
_txPower = txPower; _txPower = txPower;
} }
ble_error_t getAdvertisingPhy( ble_error_t getPhy(
ble::phy_t *primaryPhy, ble::phy_t *primaryPhy,
ble::phy_t *secondaryPhy ble::phy_t *secondaryPhy
) { ) {
@ -414,7 +414,7 @@ class GapExtendedAdvertisingParams {
return BLE_ERROR_NONE; return BLE_ERROR_NONE;
} }
void setAdvertisingPhy( void setPhy(
ble::phy_t primaryPhy, ble::phy_t primaryPhy,
ble::phy_t secondaryPhy ble::phy_t secondaryPhy
) { ) {
@ -422,29 +422,33 @@ class GapExtendedAdvertisingParams {
_secondaryPhy = secondaryPhy; _secondaryPhy = secondaryPhy;
} }
uint8_t getSecondaryAdvertisingMaxSkip() { uint8_t getSecondaryMaxSkip() {
return _eventNumber; return _eventNumber;
} }
void setSecondaryAdvertisingMaxSkip( void setSecondaryMaxSkip(
uint8_t eventNumber uint8_t eventNumber
) { ) {
_eventNumber = eventNumber; _eventNumber = eventNumber;
} }
void enableScanRequestNotification( void setScanRequestNotification(
bool enable bool enable = true
) { ) {
_notifyOnScan = enable; _notifyOnScan = enable;
} }
bool getScanRequestNotification() {
return _notifyOnScan;
}
/**/ /**/
uint32_t getMinPrimaryAdvertisingInterval() const { uint32_t getMinPrimaryInterval() const {
return _minInterval; return _minInterval;
} }
uint32_t getMinPrimaryAdvertisingInterval() const { uint32_t getMaxPrimaryInterval() const {
return _maxInterval; return _maxInterval;
} }
@ -456,6 +460,14 @@ class GapExtendedAdvertisingParams {
return _peerAddressType; return _peerAddressType;
}; };
ble::phy_t getPrimaryPhy() {
return _primaryPhy;
}
ble::phy_t getSecondaryPhy() {
return _secondaryPhy;
}
private: private:
ble::advertising_type_t _advType; ble::advertising_type_t _advType;
uint32_t _minInterval; uint32_t _minInterval;

View File

@ -47,6 +47,8 @@ class GenericGap : public ::Gap,
public pal::Gap::EventHandler { public pal::Gap::EventHandler {
public: public:
/* TODO: move to config */
static const size_t MAX_ADVERTISING_SETS = 64;
/** /**
* Construct a GenericGap instance for a given BLE instance ID. * Construct a GenericGap instance for a given BLE instance ID.
* *
@ -73,6 +75,30 @@ public:
*/ */
virtual ~GenericGap(); virtual ~GenericGap();
uint8_t getMaxAdvertisingSetNumber();
uint8_t getMaxAdvertisingDataLength();
ble_error_t createAdvertisingSet(AdvHandle_t* handle);
ble_error_t destroyAdvertisingSet(AdvHandle_t handle);
ble_error_t setAdvertisingParams(AdvHandle_t handle, const GapAdvertisingParams* params);
ble_error_t setAdvertisingParams(AdvHandle_t handle, const GapExtendedAdvertisingParams* params);
ble_error_t setAdvertisingPayload(AdvHandle_t handle, const GapAdvertisingData* payload);
ble_error_t setAdvertisingScanResponse(AdvHandle_t handle, const GapAdvertisingData* response);
ble_error_t startAdvertising(AdvHandle_t handle, uint8_t maxEvents = 0, uint32_t maxDuration = 0);
ble_error_t stopAdvertising(AdvHandle_t handle);
bool isAdvertisingActive(AdvHandle_t handle) const;
void init_extended_advertising();
/** /**
* @see Gap::setAddress * @see Gap::setAddress
*/ */
@ -316,7 +342,9 @@ public:
/** /**
* @see Gap::startAdvertising * @see Gap::startAdvertising
*/ */
virtual ble_error_t startAdvertising(const GapAdvertisingParams &params); virtual ble_error_t startAdvertising(
const GapAdvertisingParams &params
);
/** /**
* @see Gap::reset * @see Gap::reset
@ -433,6 +461,42 @@ private:
mbed::Timeout _scan_timeout; mbed::Timeout _scan_timeout;
mbed::Ticker _address_rotation_ticker; mbed::Ticker _address_rotation_ticker;
pal::ConnectionEventMonitor::EventHandler *_connection_event_handler; pal::ConnectionEventMonitor::EventHandler *_connection_event_handler;
uint8_t _existing_sets[(MAX_ADVERTISING_SETS / 8) + 1];
uint8_t _active_sets[(MAX_ADVERTISING_SETS / 8) + 1];
private:
static bool get_adv_set_bit(const uint8_t *bytes, uint8_t bit_number) {
if (bit_number > MAX_ADVERTISING_SETS) {
return false;
}
uint8_t byte = bit_number / 8;
uint8_t bit = bit_number - byte;
bytes += byte;
bool value = ((*bytes) >> bit) & 0x01;
return value;
}
static bool set_adv_set_bit(uint8_t *bytes, uint8_t bit_number) {
if (bit_number > MAX_ADVERTISING_SETS) {
return false;
}
uint8_t byte = bit_number / 8;
uint8_t bit = bit_number - byte;
bytes += byte;
*bytes |= 0x01 >> bit;
return true;
}
static bool clear_adv_set_bit(uint8_t *bytes, uint8_t bit_number) {
if (bit_number > MAX_ADVERTISING_SETS) {
return false;
}
uint8_t byte = bit_number / 8;
uint8_t bit = bit_number - byte;
bytes += byte
*bytes &= 0x00 >> bit;
return true;
}
}; };
} }

View File

@ -427,6 +427,11 @@ GenericGap::GenericGap(
_random_static_identity_address = _pal_gap.get_random_address(); _random_static_identity_address = _pal_gap.get_random_address();
_pal_gap.set_event_handler(this); _pal_gap.set_event_handler(this);
memset(_active_sets, 0, MAX_ADVERTISING_SETS);
memset(_existing_sets, 0, MAX_ADVERTISING_SETS);
/* legacy advertising always exists */
*_existing_sets = 0x01;
} }
GenericGap::~GenericGap() GenericGap::~GenericGap()
@ -1109,6 +1114,7 @@ ble_error_t GenericGap::reset(void)
Gap::reset(); Gap::reset();
_advertising_timeout.detach(); _advertising_timeout.detach();
_scan_timeout.detach(); _scan_timeout.detach();
_pal_gap.clear_advertising_sets();
return BLE_ERROR_NONE; return BLE_ERROR_NONE;
} }
@ -1555,5 +1561,189 @@ void GenericGap::set_connection_event_handler(pal::ConnectionEventMonitor::Event
_connection_event_handler = connection_event_handler; _connection_event_handler = connection_event_handler;
} }
uint8_t GenericGap::getMaxAdvertisingSetNumber() {
uint8_t set_number = _pal_gap.get_max_number_of_advertising_sets();
set_number = MAX_ADVERTISING_SETS < set_number ? MAX_ADVERTISING_SETS : set_number;
return set_number;
}
uint8_t GenericGap::getMaxAdvertisingDataLength() {
return _pal_gap.get_maximum_advertising_data_length();
}
ble_error_t GenericGap::createAdvertisingSet(AdvHandle_t* handle) {
uint8_t new_handle = 1;
while (get_adv_set_bit(_existing_sets, new_handle)) {
new_handle++;
}
if (set_adv_set_bit(_existing_sets, new_handle)) {
*handle = new_handle;
return BLE_ERROR_NONE;
}
*handle = INVALID_ADVERTISING_HANDLE;
return BLE_ERROR_OPERATION_NOT_PERMITTED;
}
ble_error_t GenericGap::destroyAdvertisingSet(AdvHandle_t handle) {
if (get_adv_set_bit(_existing_sets, handle)) {
return BLE_ERROR_INVALID_PARAM;
}
if (get_adv_set_bit(_active_sets, handle)) {
return BLE_ERROR_OPERATION_NOT_PERMITTED;
}
if (set_adv_set_bit(_existing_sets, handle)) {
return _pal_gap.remove_advertising_set(handle);
}
return BLE_ERROR_INVALID_PARAM;
}
ble_error_t GenericGap::setAdvertisingParams(AdvHandle_t handle, const GapAdvertisingParams* params) {
if (handle != Gap::LEGACY_ADVERTISING_HANDLE || !params) {
return BLE_ERROR_INVALID_PARAM;
}
pal::advertising_event_properties_t event_properties;//TODO
ble::advertising_type_t adv_type = params->getAdvertisingType();
AddressUseType_t use_type;
switch(adv_type) {
case ADV_SCANNABLE_UNDIRECTED:
case ADV_NON_CONNECTABLE_UNDIRECTED:
case EXT_ADV_NON_CONNECTABLE_DIRECTED:
case EXT_ADV_SCANNABLE_DIRECTED:
use_type = AddressUseType_t::PERIPHERAL_NON_CONNECTABLE
break;
default:
use_type = AddressUseType_t::PERIPHERAL_CONNECTABLE;
}
return _pal_gap.set_extended_advertising_parameters(
(pal::advertising_handle_t)Gap::LEGACY_ADVERTISING_HANDLE,
event_properties,
(pal::advertising_interval_t)params->getIntervalInADVUnits(),
(pal::advertising_interval_t)params->getIntervalInADVUnits(),
pal::advertising_channel_map_t::ALL_ADVERTISING_CHANNELS,
(pal::own_address_type_t)get_own_address_type(use_type),
pal::advertising_peer_address_type_t::PUBLIC_ADDRESS,
params->getPeerAddress(),
(pal::advertising_filter_policy_t)_advertising_filter_policy,
(pal::advertising_power_t)params->getTxPower(),
params->getPrimaryPhy(),
params->getSecondaryMaxSkip(),
params->getSecondaryPhy(),
0,
params->getScanRequestNotification()
);
}
ble_error_t GenericGap::setAdvertisingParams(AdvHandle_t handle, const GapExtendedAdvertisingParams* params) {
if (!get_adv_set_bit(_existing_sets, handle) || !params) {
return BLE_ERROR_INVALID_PARAM;
}
pal::advertising_channel_map_t channel_map; /*TODO translate*/
uint8_t sid;//TODO
pal::advertising_event_properties_t event_properties;//TODO
//params->getAdvertisingType()
return _pal_gap.set_extended_advertising_parameters(
(pal::advertising_handle_t)handle,
event_properties,
(pal::advertising_interval_t)params->getMinPrimaryInterval(),
(pal::advertising_interval_t)params->getMaxPrimaryInterval(),
channel_map,
(pal::own_address_type_t)params->getOwnAddressType(),
(pal::advertising_peer_address_type_t)params->getPeerAddressType(),
params->getPeerAddress(),
(pal::advertising_filter_policy_t)params->getPolicyMode(),
(pal::advertising_power_t)params->getTxPower(),
params->getPrimaryPhy(),
params->getSecondaryMaxSkip(),
params->getSecondaryPhy(),
sid,
params->getScanRequestNotification()
);
}
ble_error_t GenericGap::setAdvertisingPayload(AdvHandle_t handle, const GapAdvertisingData* payload) {
if (!get_adv_set_bit(_existing_sets, handle) || !payload) {
return BLE_ERROR_INVALID_PARAM;
}
return _pal_gap.set_extended_advertising_data(
handle,
/*TODO fragment*/ pal::advertising_fragment_description_t::FIRST_FRAGMENT,
payload->setMinimiseFragmentation,
payload->getPayloadLen(),
payload->getPayload()
);
}
ble_error_t GenericGap::setAdvertisingScanResponse(AdvHandle_t handle, const GapAdvertisingData* response) {
if (!get_adv_set_bit(_existing_sets, handle) || !response) {
return BLE_ERROR_INVALID_PARAM;
}
return _pal_gap.set_extended_scan_response_data(
handle,
/*TODO fragment*/ pal::advertising_fragment_description_t::FIRST_FRAGMENT,
response->setMinimiseFragmentation,
response->getPayloadLen(),
response->getPayload()
);
}
ble_error_t GenericGap::startAdvertising(
AdvHandle_t handle,
uint8_t maxEvents,
uint32_t maxDuration
) {
if (!get_adv_set_bit(_existing_sets, handle)) {
return BLE_ERROR_INVALID_PARAM;
}
/* round up */
uint16_t duration_10ms = maxDuration ? (maxDuration - 1) / 10 + 1 : 0 ;
ble_error_t status = _pal_gap.extended_advertising_enable(
true,
1,
&handle,
&duration_10ms,
&maxEvents
);
if (status == BLE_ERROR_NONE) {
set_adv_set_bit(_active_sets, handle);
}
return status;
}
ble_error_t GenericGap::stopAdvertising(AdvHandle_t handle) {
if (get_adv_set_bit(_existing_sets, handle)) {
return BLE_ERROR_INVALID_PARAM;
}
return _pal_gap.extended_advertising_enable(
true,
1,
&handle,
NULL,
NULL
);
}
bool GenericGap::isAdvertisingActive(AdvHandle_t handle) const {
return get_adv_set_bit(_active_sets, handle);
}
} // namespace generic } // namespace generic
} // namespace ble } // namespace ble