mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #9096 from pan-/fix-enforce-size-limits
BLE: Enforce advertising data payload limitspull/9415/head
commit
284781a565
|
@ -123,13 +123,20 @@ public:
|
||||||
* @param[in] minInterval, maxInterval Time interval between two advertisement.
|
* @param[in] minInterval, maxInterval Time interval between two advertisement.
|
||||||
* A range is provided to the LE subsystem, so it can adjust the advertising
|
* A range is provided to the LE subsystem, so it can adjust the advertising
|
||||||
* interval with other transmission happening on the BLE radio.
|
* interval with other transmission happening on the BLE radio.
|
||||||
|
* @param[in] useLegacyPDU If true legacy PDU shall be used for advertising.
|
||||||
|
*
|
||||||
|
* @note If CONNECTABLE_UNDIRECTED or CONNECTABLE_DIRECTED advertising is used
|
||||||
|
* you must use legacy PDU.
|
||||||
*
|
*
|
||||||
* @note If values in input are out of range, they will be normalized.
|
* @note If values in input are out of range, they will be normalized.
|
||||||
|
*
|
||||||
|
* @note If type selected is incompatible with non legacy PDU, legacy PDU will be used.
|
||||||
*/
|
*/
|
||||||
AdvertisingParameters(
|
AdvertisingParameters(
|
||||||
advertising_type_t advType = advertising_type_t::CONNECTABLE_UNDIRECTED,
|
advertising_type_t advType = advertising_type_t::CONNECTABLE_UNDIRECTED,
|
||||||
adv_interval_t minInterval = adv_interval_t(DEFAULT_ADVERTISING_INTERVAL_MIN),
|
adv_interval_t minInterval = adv_interval_t(DEFAULT_ADVERTISING_INTERVAL_MIN),
|
||||||
adv_interval_t maxInterval = adv_interval_t(DEFAULT_ADVERTISING_INTERVAL_MAX)
|
adv_interval_t maxInterval = adv_interval_t(DEFAULT_ADVERTISING_INTERVAL_MAX),
|
||||||
|
bool useLegacyPDU = true
|
||||||
) :
|
) :
|
||||||
_advType(advType),
|
_advType(advType),
|
||||||
_minInterval(minInterval),
|
_minInterval(minInterval),
|
||||||
|
@ -147,27 +154,91 @@ public:
|
||||||
_channel39(true),
|
_channel39(true),
|
||||||
_anonymous(false),
|
_anonymous(false),
|
||||||
_notifyOnScan(false),
|
_notifyOnScan(false),
|
||||||
_legacyPDU(true),
|
_legacyPDU(useLegacyPDU),
|
||||||
_includeHeaderTxPower(false)
|
_includeHeaderTxPower(false)
|
||||||
{
|
{
|
||||||
/* Min interval is slightly larger than in other modes. */
|
normalize();
|
||||||
if (_advType == advertising_type_t::NON_CONNECTABLE_UNDIRECTED) {
|
}
|
||||||
_minInterval = adv_interval_t(std::max(_minInterval.value(), GAP_ADV_PARAMS_INTERVAL_MIN_NONCON));
|
|
||||||
_maxInterval = adv_interval_t(std::max(_maxInterval.value(), GAP_ADV_PARAMS_INTERVAL_MIN_NONCON));
|
/**
|
||||||
}
|
* Construct an instance of GapAdvertisingParams.
|
||||||
|
*
|
||||||
|
* @param[in] advType Type of advertising.
|
||||||
|
* @param[in] useLegacyPDU If true legacy PDU shall be used for advertising.
|
||||||
|
*
|
||||||
|
* @note If CONNECTABLE_UNDIRECTED or CONNECTABLE_DIRECTED advertising is used
|
||||||
|
* you must use legacy PDU.
|
||||||
|
*
|
||||||
|
* @note If type selected is incompatible with non legacy PDU, legacy PDU will be used.
|
||||||
|
*/
|
||||||
|
AdvertisingParameters(
|
||||||
|
advertising_type_t advType,
|
||||||
|
bool useLegacyPDU
|
||||||
|
) :
|
||||||
|
_advType(advType),
|
||||||
|
_minInterval(adv_interval_t(DEFAULT_ADVERTISING_INTERVAL_MIN)),
|
||||||
|
_maxInterval(adv_interval_t(DEFAULT_ADVERTISING_INTERVAL_MAX)),
|
||||||
|
_peerAddressType(target_peer_address_type_t::PUBLIC),
|
||||||
|
_ownAddressType(own_address_type_t::RANDOM),
|
||||||
|
_policy(advertising_filter_policy_t::NO_FILTER),
|
||||||
|
_primaryPhy(phy_t::LE_1M),
|
||||||
|
_secondaryPhy(phy_t::LE_1M),
|
||||||
|
_peerAddress(),
|
||||||
|
_txPower(127),
|
||||||
|
_maxSkip(0),
|
||||||
|
_channel37(true),
|
||||||
|
_channel38(true),
|
||||||
|
_channel39(true),
|
||||||
|
_anonymous(false),
|
||||||
|
_notifyOnScan(false),
|
||||||
|
_legacyPDU(useLegacyPDU),
|
||||||
|
_includeHeaderTxPower(false)
|
||||||
|
{
|
||||||
|
normalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* Update the advertising type and whether to use legacy PDU.
|
||||||
|
*
|
||||||
|
* @note If legacy PDU is not used then you cannot use
|
||||||
|
* CONNECTABLE_UNDIRECTED nor CONNECTABLE_DIRECTED.
|
||||||
|
*
|
||||||
|
* @param[in] newAdvType The new advertising type.
|
||||||
|
*
|
||||||
|
* @param[in] legacy If true, legacy PDU will be used.
|
||||||
|
*
|
||||||
|
* @return reference to this object.
|
||||||
|
*/
|
||||||
|
AdvertisingParameters &setType(advertising_type_t newAdvType, bool legacy)
|
||||||
|
{
|
||||||
|
if (newAdvType == advertising_type_t::CONNECTABLE_UNDIRECTED ||
|
||||||
|
newAdvType == advertising_type_t::CONNECTABLE_DIRECTED) {
|
||||||
|
/* these types can only be used with legacy PDUs */
|
||||||
|
MBED_ASSERT(legacy);
|
||||||
|
}
|
||||||
|
_advType = newAdvType;
|
||||||
|
_legacyPDU = legacy;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the advertising type.
|
* Update the advertising type.
|
||||||
*
|
*
|
||||||
|
* @note If legacy PDU is not used then you cannot use
|
||||||
|
* CONNECTABLE_UNDIRECTED nor CONNECTABLE_DIRECTED.
|
||||||
|
*
|
||||||
* @param[in] newAdvType The new advertising type.
|
* @param[in] newAdvType The new advertising type.
|
||||||
*
|
*
|
||||||
* @return reference to this object.
|
* @return reference to this object.
|
||||||
*/
|
*/
|
||||||
AdvertisingParameters &setType(advertising_type_t newAdvType)
|
AdvertisingParameters &setType(advertising_type_t newAdvType)
|
||||||
{
|
{
|
||||||
|
if (newAdvType == advertising_type_t::CONNECTABLE_UNDIRECTED ||
|
||||||
|
newAdvType == advertising_type_t::CONNECTABLE_DIRECTED) {
|
||||||
|
/* these types can only be used with legacy PDUs */
|
||||||
|
MBED_ASSERT(_legacyPDU);
|
||||||
|
}
|
||||||
_advType = newAdvType;
|
_advType = newAdvType;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -448,10 +519,19 @@ public:
|
||||||
*
|
*
|
||||||
* @param enable If true, legacy PDU will be used.
|
* @param enable If true, legacy PDU will be used.
|
||||||
*
|
*
|
||||||
|
* @note If CONNECTABLE_UNDIRECTED or CONNECTABLE_DIRECTED advertising is used
|
||||||
|
* you must use legacy PDU.
|
||||||
|
*
|
||||||
* @return A reference to this object.
|
* @return A reference to this object.
|
||||||
*/
|
*/
|
||||||
AdvertisingParameters &setUseLegacyPDU(bool enable = true)
|
AdvertisingParameters &setUseLegacyPDU(bool enable = true)
|
||||||
{
|
{
|
||||||
|
if (!enable) {
|
||||||
|
/* these types can only be used with legacy PDUs */
|
||||||
|
MBED_ASSERT((_advType != advertising_type_t::CONNECTABLE_UNDIRECTED) &&
|
||||||
|
(_advType != advertising_type_t::CONNECTABLE_DIRECTED));
|
||||||
|
}
|
||||||
|
|
||||||
_legacyPDU = enable;
|
_legacyPDU = enable;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -490,6 +570,8 @@ public:
|
||||||
*
|
*
|
||||||
* @param enable Advertising anonymous if true.
|
* @param enable Advertising anonymous if true.
|
||||||
*
|
*
|
||||||
|
* @note You may not use anonymous advertising with periodic advertising on the same set.
|
||||||
|
*
|
||||||
* @return reference to this object.
|
* @return reference to this object.
|
||||||
*/
|
*/
|
||||||
AdvertisingParameters &setAnonymousAdvertising(bool enable)
|
AdvertisingParameters &setAnonymousAdvertising(bool enable)
|
||||||
|
@ -507,6 +589,23 @@ public:
|
||||||
return _anonymous;
|
return _anonymous;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Enforce limits on parameters.
|
||||||
|
*/
|
||||||
|
void normalize()
|
||||||
|
{
|
||||||
|
/* Min interval is slightly larger than in other modes. */
|
||||||
|
if (_advType == advertising_type_t::NON_CONNECTABLE_UNDIRECTED) {
|
||||||
|
_minInterval = adv_interval_t(std::max(_minInterval.value(), GAP_ADV_PARAMS_INTERVAL_MIN_NONCON));
|
||||||
|
_maxInterval = adv_interval_t(std::max(_maxInterval.value(), GAP_ADV_PARAMS_INTERVAL_MIN_NONCON));
|
||||||
|
}
|
||||||
|
if (_advType == advertising_type_t::CONNECTABLE_DIRECTED ||
|
||||||
|
_advType == advertising_type_t::CONNECTABLE_UNDIRECTED) {
|
||||||
|
_legacyPDU = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
advertising_type_t _advType;
|
advertising_type_t _advType;
|
||||||
/* The advertising interval in ADV duration units (in other words, 0.625ms). */
|
/* The advertising interval in ADV duration units (in other words, 0.625ms). */
|
||||||
|
|
|
@ -538,6 +538,18 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual uint16_t getMaxAdvertisingDataLength();
|
virtual uint16_t getMaxAdvertisingDataLength();
|
||||||
|
|
||||||
|
/** Return maximum advertising data length supported for connectable advertising.
|
||||||
|
*
|
||||||
|
* @return Maximum advertising data length supported for connectable advertising.
|
||||||
|
*/
|
||||||
|
virtual uint16_t getMaxConnectableAdvertisingDataLength();
|
||||||
|
|
||||||
|
/** Return maximum advertising data length you may set if advertising set is active.
|
||||||
|
*
|
||||||
|
* @return Maximum advertising data length you may set if advertising set is active.
|
||||||
|
*/
|
||||||
|
virtual uint16_t getMaxActiveSetAdvertisingDataLength();
|
||||||
|
|
||||||
/** Create an advertising set and apply the passed in parameters. The handle returned
|
/** Create an advertising set and apply the passed in parameters. The handle returned
|
||||||
* by this function must be used for all other calls that accept an advertising handle.
|
* by this function must be used for all other calls that accept an advertising handle.
|
||||||
* When done with advertising, remove from the system using destroyAdvertisingSet().
|
* When done with advertising, remove from the system using destroyAdvertisingSet().
|
||||||
|
@ -583,6 +595,10 @@ public:
|
||||||
* @param handle Advertising set handle.
|
* @param handle Advertising set handle.
|
||||||
* @param payload Advertising payload.
|
* @param payload Advertising payload.
|
||||||
*
|
*
|
||||||
|
* @note If advertising set is active you may only set payload of length equal or less
|
||||||
|
* than getMaxActiveSetAdvertisingDataLength(). If you require a longer payload you must
|
||||||
|
* stop the advertising set, set the payload and restart the set.
|
||||||
|
*
|
||||||
* @return BLE_ERROR_NONE on success.
|
* @return BLE_ERROR_NONE on success.
|
||||||
*
|
*
|
||||||
* @see ble::AdvertisingDataBuilder to build a payload.
|
* @see ble::AdvertisingDataBuilder to build a payload.
|
||||||
|
@ -598,6 +614,10 @@ public:
|
||||||
* @param handle Advertising set handle.
|
* @param handle Advertising set handle.
|
||||||
* @param response Advertising scan response.
|
* @param response Advertising scan response.
|
||||||
*
|
*
|
||||||
|
* @note If advertising set is active you may only set payload of length equal or less
|
||||||
|
* than getMaxActiveSetAdvertisingDataLength(). If you require a longer payload you must
|
||||||
|
* stop the advertising set, set the payload and restart the set.
|
||||||
|
*
|
||||||
* @return BLE_ERROR_NONE on success.
|
* @return BLE_ERROR_NONE on success.
|
||||||
*
|
*
|
||||||
* @see ble::AdvertisingDataBuilder to build a payload.
|
* @see ble::AdvertisingDataBuilder to build a payload.
|
||||||
|
@ -663,6 +683,11 @@ public:
|
||||||
* @param payload Advertising payload.
|
* @param payload Advertising payload.
|
||||||
* @return BLE_ERROR_NONE on success.
|
* @return BLE_ERROR_NONE on success.
|
||||||
*
|
*
|
||||||
|
* @note If advertising set is active you may only set payload of length equal or less
|
||||||
|
* than getMaxActiveSetAdvertisingDataLength(). If you require a longer payload you must
|
||||||
|
* stop the advertising set, set the payload and restart the set. Stopping the set will
|
||||||
|
* cause peers to lose sync on the periodic set.
|
||||||
|
*
|
||||||
* @see ble::AdvertisingDataBuilder to build a payload.
|
* @see ble::AdvertisingDataBuilder to build a payload.
|
||||||
*
|
*
|
||||||
* @version 5+
|
* @version 5+
|
||||||
|
|
|
@ -50,7 +50,6 @@ class GenericGap :
|
||||||
public:
|
public:
|
||||||
/* TODO: move to config */
|
/* TODO: move to config */
|
||||||
static const uint8_t MAX_ADVERTISING_SETS = 15;
|
static const uint8_t MAX_ADVERTISING_SETS = 15;
|
||||||
static const size_t MAX_HCI_DATA_LENGTH = 251;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a GenericGap.
|
* Construct a GenericGap.
|
||||||
|
@ -92,6 +91,14 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual uint16_t getMaxAdvertisingDataLength();
|
virtual uint16_t getMaxAdvertisingDataLength();
|
||||||
|
|
||||||
|
/** @copydoc Gap::getMaxConnectableAdvertisingDataLength
|
||||||
|
*/
|
||||||
|
virtual uint16_t getMaxConnectableAdvertisingDataLength();
|
||||||
|
|
||||||
|
/** @copydoc Gap::getMaxActiveSetAdvertisingDataLength
|
||||||
|
*/
|
||||||
|
virtual uint16_t getMaxActiveSetAdvertisingDataLength();
|
||||||
|
|
||||||
/** @copydoc Gap::createAdvertisingSet
|
/** @copydoc Gap::createAdvertisingSet
|
||||||
*/
|
*/
|
||||||
virtual ble_error_t createAdvertisingSet(
|
virtual ble_error_t createAdvertisingSet(
|
||||||
|
@ -781,6 +788,8 @@ private:
|
||||||
BitArray<MAX_ADVERTISING_SETS> _existing_sets;
|
BitArray<MAX_ADVERTISING_SETS> _existing_sets;
|
||||||
BitArray<MAX_ADVERTISING_SETS> _active_sets;
|
BitArray<MAX_ADVERTISING_SETS> _active_sets;
|
||||||
BitArray<MAX_ADVERTISING_SETS> _active_periodic_sets;
|
BitArray<MAX_ADVERTISING_SETS> _active_periodic_sets;
|
||||||
|
BitArray<MAX_ADVERTISING_SETS> _connectable_payload_size_exceeded;
|
||||||
|
BitArray<MAX_ADVERTISING_SETS> _set_is_connectable;
|
||||||
|
|
||||||
// deprecation flags
|
// deprecation flags
|
||||||
mutable bool _deprecated_scan_api_used : 1;
|
mutable bool _deprecated_scan_api_used : 1;
|
||||||
|
|
|
@ -764,6 +764,23 @@ struct Gap {
|
||||||
*/
|
*/
|
||||||
virtual uint16_t get_maximum_advertising_data_length() = 0;
|
virtual uint16_t get_maximum_advertising_data_length() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query the maximum data length the controller supports in an advertising set
|
||||||
|
* using connectable advertising.
|
||||||
|
*
|
||||||
|
* @return The length in byte the controller can support in an advertising set
|
||||||
|
* for connectable advertising.
|
||||||
|
*/
|
||||||
|
virtual uint16_t get_maximum_connectable_advertising_data_length() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query the maximum payload length for a single HCI packet carrying partial
|
||||||
|
* (or complete if it fits) data for advertising set.
|
||||||
|
*
|
||||||
|
* @return Max size of the HCI packet transporting the data.
|
||||||
|
*/
|
||||||
|
virtual uint8_t get_maximum_hci_advertising_data_length() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query the maximum number of concurrent advertising sets that is supported
|
* Query the maximum number of concurrent advertising sets that is supported
|
||||||
* by the controller.
|
* by the controller.
|
||||||
|
|
|
@ -36,6 +36,18 @@ uint16_t Gap::getMaxAdvertisingDataLength()
|
||||||
return LEGACY_ADVERTISING_MAX_SIZE;
|
return LEGACY_ADVERTISING_MAX_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t Gap::getMaxConnectableAdvertisingDataLength()
|
||||||
|
{
|
||||||
|
/* Requesting action from porter(s): override this API if this capability is supported. */
|
||||||
|
return LEGACY_ADVERTISING_MAX_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t Gap::getMaxActiveSetAdvertisingDataLength()
|
||||||
|
{
|
||||||
|
/* Requesting action from porter(s): override this API if this capability is supported. */
|
||||||
|
return LEGACY_ADVERTISING_MAX_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
ble_error_t Gap::createAdvertisingSet(
|
ble_error_t Gap::createAdvertisingSet(
|
||||||
advertising_handle_t *handle,
|
advertising_handle_t *handle,
|
||||||
const AdvertisingParameters ¶meters
|
const AdvertisingParameters ¶meters
|
||||||
|
|
|
@ -1393,6 +1393,8 @@ ble_error_t GenericGap::reset(void)
|
||||||
_existing_sets.clear();
|
_existing_sets.clear();
|
||||||
_active_sets.clear();
|
_active_sets.clear();
|
||||||
_active_periodic_sets.clear();
|
_active_periodic_sets.clear();
|
||||||
|
_connectable_payload_size_exceeded.clear();
|
||||||
|
_set_is_connectable.clear();
|
||||||
|
|
||||||
/* clear advertising set data on the controller */
|
/* clear advertising set data on the controller */
|
||||||
_pal_gap.clear_advertising_sets();
|
_pal_gap.clear_advertising_sets();
|
||||||
|
@ -2008,8 +2010,6 @@ void GenericGap::set_connection_event_handler(pal::ConnectionEventMonitor::Event
|
||||||
|
|
||||||
const uint8_t GenericGap::MAX_ADVERTISING_SETS;
|
const uint8_t GenericGap::MAX_ADVERTISING_SETS;
|
||||||
|
|
||||||
const size_t GenericGap::MAX_HCI_DATA_LENGTH;
|
|
||||||
|
|
||||||
uint8_t GenericGap::getMaxAdvertisingSetNumber()
|
uint8_t GenericGap::getMaxAdvertisingSetNumber()
|
||||||
{
|
{
|
||||||
useVersionTwoAPI();
|
useVersionTwoAPI();
|
||||||
|
@ -2028,6 +2028,18 @@ uint16_t GenericGap::getMaxAdvertisingDataLength()
|
||||||
return _pal_gap.get_maximum_advertising_data_length();
|
return _pal_gap.get_maximum_advertising_data_length();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t GenericGap::getMaxConnectableAdvertisingDataLength()
|
||||||
|
{
|
||||||
|
useVersionTwoAPI();
|
||||||
|
return _pal_gap.get_maximum_connectable_advertising_data_length();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t GenericGap::getMaxActiveSetAdvertisingDataLength()
|
||||||
|
{
|
||||||
|
useVersionTwoAPI();
|
||||||
|
return _pal_gap.get_maximum_hci_advertising_data_length();
|
||||||
|
}
|
||||||
|
|
||||||
ble_error_t GenericGap::createAdvertisingSet(
|
ble_error_t GenericGap::createAdvertisingSet(
|
||||||
advertising_handle_t *handle,
|
advertising_handle_t *handle,
|
||||||
const AdvertisingParameters ¶meters
|
const AdvertisingParameters ¶meters
|
||||||
|
@ -2042,6 +2054,8 @@ ble_error_t GenericGap::createAdvertisingSet(
|
||||||
uint8_t new_handle = LEGACY_ADVERTISING_HANDLE + 1;
|
uint8_t new_handle = LEGACY_ADVERTISING_HANDLE + 1;
|
||||||
uint8_t end = getMaxAdvertisingSetNumber();
|
uint8_t end = getMaxAdvertisingSetNumber();
|
||||||
|
|
||||||
|
*handle = INVALID_ADVERTISING_HANDLE;
|
||||||
|
|
||||||
for (; new_handle < end; ++new_handle) {
|
for (; new_handle < end; ++new_handle) {
|
||||||
if (!_existing_sets.get(new_handle)) {
|
if (!_existing_sets.get(new_handle)) {
|
||||||
ble_error_t err = setExtendedAdvertisingParameters(
|
ble_error_t err = setExtendedAdvertisingParameters(
|
||||||
|
@ -2054,11 +2068,11 @@ ble_error_t GenericGap::createAdvertisingSet(
|
||||||
|
|
||||||
_existing_sets.set(new_handle);
|
_existing_sets.set(new_handle);
|
||||||
*handle = new_handle;
|
*handle = new_handle;
|
||||||
|
|
||||||
return BLE_ERROR_NONE;
|
return BLE_ERROR_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*handle = INVALID_ADVERTISING_HANDLE;
|
|
||||||
return BLE_ERROR_NO_MEM;
|
return BLE_ERROR_NO_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2095,6 +2109,8 @@ ble_error_t GenericGap::destroyAdvertisingSet(advertising_handle_t handle)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_connectable_payload_size_exceeded.clear(handle);
|
||||||
|
_set_is_connectable.clear(handle);
|
||||||
_existing_sets.clear(handle);
|
_existing_sets.clear(handle);
|
||||||
return BLE_ERROR_NONE;
|
return BLE_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
@ -2149,6 +2165,18 @@ ble_error_t GenericGap::setExtendedAdvertisingParameters(
|
||||||
return BLE_ERROR_INVALID_PARAM;
|
return BLE_ERROR_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_active_sets.get(handle)) {
|
||||||
|
return BLE_ERROR_OPERATION_NOT_PERMITTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for illegal parameter combination */
|
||||||
|
if ((params.getType() == advertising_type_t::CONNECTABLE_UNDIRECTED ||
|
||||||
|
params.getType() == advertising_type_t::CONNECTABLE_DIRECTED) &&
|
||||||
|
params.getUseLegacyPDU() == false) {
|
||||||
|
/* these types can only be used with legacy PDUs */
|
||||||
|
return BLE_ERROR_INVALID_PARAM;
|
||||||
|
}
|
||||||
|
|
||||||
pal::advertising_event_properties_t event_properties(params.getType());
|
pal::advertising_event_properties_t event_properties(params.getType());
|
||||||
event_properties.include_tx_power = params.getTxPowerInHeader();
|
event_properties.include_tx_power = params.getTxPowerInHeader();
|
||||||
event_properties.omit_advertiser_address = params.getAnonymousAdvertising();
|
event_properties.omit_advertiser_address = params.getAnonymousAdvertising();
|
||||||
|
@ -2182,6 +2210,12 @@ ble_error_t GenericGap::setExtendedAdvertisingParameters(
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event_properties.connectable) {
|
||||||
|
_set_is_connectable.set(handle);
|
||||||
|
} else {
|
||||||
|
_set_is_connectable.clear(handle);
|
||||||
|
}
|
||||||
|
|
||||||
return _pal_gap.set_advertising_set_random_address(
|
return _pal_gap.set_advertising_set_random_address(
|
||||||
handle,
|
handle,
|
||||||
_random_static_identity_address
|
_random_static_identity_address
|
||||||
|
@ -2270,32 +2304,52 @@ ble_error_t GenericGap::setAdvertisingData(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (payload.size() > getMaxAdvertisingDataLength()) {
|
if (payload.size() > getMaxAdvertisingDataLength()) {
|
||||||
|
MBED_WARNING(MBED_ERROR_INVALID_SIZE, "Payload size exceeds getMaxAdvertisingDataLength().");
|
||||||
return BLE_ERROR_INVALID_PARAM;
|
return BLE_ERROR_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_active_sets.get(handle) && payload.size() > getMaxActiveSetAdvertisingDataLength()) {
|
||||||
|
MBED_WARNING(MBED_ERROR_INVALID_SIZE, "Payload size for active sets needs to fit in a single operation"
|
||||||
|
" - not greater than getMaxActiveSetAdvertisingDataLength().");
|
||||||
|
return BLE_ERROR_INVALID_PARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!scan_response) {
|
||||||
|
if (payload.size() > getMaxConnectableAdvertisingDataLength()) {
|
||||||
|
if (_active_sets.get(handle) && _set_is_connectable.get(handle)) {
|
||||||
|
MBED_WARNING(MBED_ERROR_INVALID_SIZE, "Payload size for connectable advertising"
|
||||||
|
" exceeds getMaxAdvertisingDataLength().");
|
||||||
|
return BLE_ERROR_INVALID_PARAM;
|
||||||
|
} else {
|
||||||
|
_connectable_payload_size_exceeded.set(handle);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_connectable_payload_size_exceeded.clear(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// select the pal function
|
// select the pal function
|
||||||
set_data_fn_t set_data = scan_response ?
|
set_data_fn_t set_data = scan_response ?
|
||||||
&pal::Gap::set_extended_scan_response_data :
|
&pal::Gap::set_extended_scan_response_data :
|
||||||
&pal::Gap::set_extended_advertising_data;
|
&pal::Gap::set_extended_advertising_data;
|
||||||
|
|
||||||
for (size_t i = 0, end = payload.size();
|
const size_t hci_length = _pal_gap.get_maximum_hci_advertising_data_length();
|
||||||
(i < end) || (i == 0 && end == 0);
|
|
||||||
i += MAX_HCI_DATA_LENGTH)
|
for (size_t i = 0, end = payload.size(); (i < end) || (i == 0 && end == 0); i += hci_length) {
|
||||||
{
|
|
||||||
// select the operation based on the index
|
// select the operation based on the index
|
||||||
op_t op(op_t::INTERMEDIATE_FRAGMENT);
|
op_t op(op_t::INTERMEDIATE_FRAGMENT);
|
||||||
if (end < MAX_HCI_DATA_LENGTH) {
|
if (end < hci_length) {
|
||||||
op = op_t::COMPLETE_FRAGMENT;
|
op = op_t::COMPLETE_FRAGMENT;
|
||||||
} else if (i == 0) {
|
} else if (i == 0) {
|
||||||
op = op_t::FIRST_FRAGMENT;
|
op = op_t::FIRST_FRAGMENT;
|
||||||
} else if ((end - i) <= MAX_HCI_DATA_LENGTH) {
|
} else if ((end - i) <= hci_length) {
|
||||||
op = op_t::LAST_FRAGMENT;
|
op = op_t::LAST_FRAGMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract the payload
|
// extract the payload
|
||||||
mbed::Span<const uint8_t> sub_payload = payload.subspan(
|
mbed::Span<const uint8_t> sub_payload = payload.subspan(
|
||||||
i,
|
i,
|
||||||
std::min(MAX_HCI_DATA_LENGTH, (end - i))
|
std::min(hci_length, (end - i))
|
||||||
);
|
);
|
||||||
|
|
||||||
// set the payload
|
// set the payload
|
||||||
|
@ -2332,6 +2386,11 @@ ble_error_t GenericGap::startAdvertising(
|
||||||
return BLE_ERROR_INVALID_PARAM;
|
return BLE_ERROR_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_connectable_payload_size_exceeded.get(handle) && _set_is_connectable.get(handle)) {
|
||||||
|
MBED_WARNING(MBED_ERROR_INVALID_SIZE, "Payload size exceeds size allowed for connectable advertising.");
|
||||||
|
return BLE_ERROR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_extended_advertising_available()) {
|
if (is_extended_advertising_available()) {
|
||||||
error = _pal_gap.extended_advertising_enable(
|
error = _pal_gap.extended_advertising_enable(
|
||||||
/* enable */ true,
|
/* enable */ true,
|
||||||
|
@ -2486,24 +2545,26 @@ ble_error_t GenericGap::setPeriodicAdvertisingPayload(
|
||||||
|
|
||||||
typedef pal::advertising_fragment_description_t op_t;
|
typedef pal::advertising_fragment_description_t op_t;
|
||||||
|
|
||||||
for (size_t i = 0, end = payload.size();
|
const size_t hci_length = _pal_gap.get_maximum_hci_advertising_data_length();
|
||||||
(i < end) || (i == 0 && end == 0);
|
size_t i = 0;
|
||||||
i += MAX_HCI_DATA_LENGTH
|
size_t end = payload.size();
|
||||||
) {
|
|
||||||
|
/* always do at least one iteration for empty payload */
|
||||||
|
do {
|
||||||
// select the operation based on the index
|
// select the operation based on the index
|
||||||
op_t op(op_t::INTERMEDIATE_FRAGMENT);
|
op_t op(op_t::INTERMEDIATE_FRAGMENT);
|
||||||
if (end < MAX_HCI_DATA_LENGTH) {
|
if (end < hci_length) {
|
||||||
op = op_t::COMPLETE_FRAGMENT;
|
op = op_t::COMPLETE_FRAGMENT;
|
||||||
} else if (i == 0) {
|
} else if (i == 0) {
|
||||||
op = op_t::FIRST_FRAGMENT;
|
op = op_t::FIRST_FRAGMENT;
|
||||||
} else if ((end - i) <= MAX_HCI_DATA_LENGTH) {
|
} else if ((end - i) <= hci_length) {
|
||||||
op = op_t::LAST_FRAGMENT;
|
op = op_t::LAST_FRAGMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract the payload
|
// extract the payload
|
||||||
mbed::Span<const uint8_t> sub_payload = payload.subspan(
|
mbed::Span<const uint8_t> sub_payload = payload.subspan(
|
||||||
i,
|
i,
|
||||||
std::min(MAX_HCI_DATA_LENGTH, (end - i))
|
std::min(hci_length, (end - i))
|
||||||
);
|
);
|
||||||
|
|
||||||
ble_error_t err = _pal_gap.set_periodic_advertising_data(
|
ble_error_t err = _pal_gap.set_periodic_advertising_data(
|
||||||
|
@ -2516,7 +2577,9 @@ ble_error_t GenericGap::setPeriodicAdvertisingPayload(
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
i += hci_length;
|
||||||
|
} while (i < end);
|
||||||
|
|
||||||
return BLE_ERROR_NONE;
|
return BLE_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,6 +221,10 @@ public:
|
||||||
|
|
||||||
virtual uint16_t get_maximum_advertising_data_length();
|
virtual uint16_t get_maximum_advertising_data_length();
|
||||||
|
|
||||||
|
virtual uint16_t get_maximum_connectable_advertising_data_length();
|
||||||
|
|
||||||
|
virtual uint8_t get_maximum_hci_advertising_data_length();
|
||||||
|
|
||||||
virtual uint8_t get_max_number_of_advertising_sets();
|
virtual uint8_t get_max_number_of_advertising_sets();
|
||||||
|
|
||||||
virtual ble_error_t remove_advertising_set(
|
virtual ble_error_t remove_advertising_set(
|
||||||
|
|
|
@ -921,6 +921,16 @@ uint16_t Gap::get_maximum_advertising_data_length()
|
||||||
return HciGetMaxAdvDataLen();
|
return HciGetMaxAdvDataLen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t Gap::get_maximum_connectable_advertising_data_length()
|
||||||
|
{
|
||||||
|
return HCI_EXT_ADV_CONN_DATA_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Gap::get_maximum_hci_advertising_data_length()
|
||||||
|
{
|
||||||
|
return HCI_EXT_ADV_DATA_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t Gap::get_max_number_of_advertising_sets()
|
uint8_t Gap::get_max_number_of_advertising_sets()
|
||||||
{
|
{
|
||||||
return std::min(HciGetNumSupAdvSets(), (uint8_t) DM_NUM_ADV_SETS);
|
return std::min(HciGetNumSupAdvSets(), (uint8_t) DM_NUM_ADV_SETS);
|
||||||
|
|
Loading…
Reference in New Issue