mirror of https://github.com/ARMmbed/mbed-os.git
generic advertising
parent
f35ebcc900
commit
6ca5041f53
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ¶ms);
|
||||
virtual ble_error_t startAdvertising(
|
||||
const GapAdvertisingParams ¶ms
|
||||
);
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue