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;
static const AdvHandle_t LEGACY_ADVERTISING_HANDLE = 0x00;
static const AdvHandle_t INVALID_ADVERTISING_HANDLE = 0xFF;
struct AdvReportOptionalInformation {
PeerAddressType_t directAddressType;

View File

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

View File

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

View File

@ -47,6 +47,8 @@ class GenericGap : public ::Gap,
public pal::Gap::EventHandler {
public:
/* TODO: move to config */
static const size_t MAX_ADVERTISING_SETS = 64;
/**
* Construct a GenericGap instance for a given BLE instance ID.
*
@ -73,6 +75,30 @@ public:
*/
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
*/
@ -316,7 +342,9 @@ public:
/**
* @see Gap::startAdvertising
*/
virtual ble_error_t startAdvertising(const GapAdvertisingParams &params);
virtual ble_error_t startAdvertising(
const GapAdvertisingParams &params
);
/**
* @see Gap::reset
@ -433,6 +461,42 @@ private:
mbed::Timeout _scan_timeout;
mbed::Ticker _address_rotation_ticker;
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();
_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()
@ -1109,6 +1114,7 @@ ble_error_t GenericGap::reset(void)
Gap::reset();
_advertising_timeout.detach();
_scan_timeout.detach();
_pal_gap.clear_advertising_sets();
return BLE_ERROR_NONE;
}
@ -1555,5 +1561,189 @@ void GenericGap::set_connection_event_handler(pal::ConnectionEventMonitor::Event
_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 ble