Skip to content

Commit 284781a

Browse files
authored
Merge pull request #9096 from pan-/fix-enforce-size-limits
BLE: Enforce advertising data payload limits
2 parents b59b93e + 3be792a commit 284781a

File tree

8 files changed

+265
-26
lines changed

8 files changed

+265
-26
lines changed

features/FEATURE_BLE/ble/gap/AdvertisingParameters.h

Lines changed: 106 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,20 @@ class AdvertisingParameters {
123123
* @param[in] minInterval, maxInterval Time interval between two advertisement.
124124
* A range is provided to the LE subsystem, so it can adjust the advertising
125125
* interval with other transmission happening on the BLE radio.
126+
* @param[in] useLegacyPDU If true legacy PDU shall be used for advertising.
127+
*
128+
* @note If CONNECTABLE_UNDIRECTED or CONNECTABLE_DIRECTED advertising is used
129+
* you must use legacy PDU.
126130
*
127131
* @note If values in input are out of range, they will be normalized.
132+
*
133+
* @note If type selected is incompatible with non legacy PDU, legacy PDU will be used.
128134
*/
129135
AdvertisingParameters(
130136
advertising_type_t advType = advertising_type_t::CONNECTABLE_UNDIRECTED,
131137
adv_interval_t minInterval = adv_interval_t(DEFAULT_ADVERTISING_INTERVAL_MIN),
132-
adv_interval_t maxInterval = adv_interval_t(DEFAULT_ADVERTISING_INTERVAL_MAX)
138+
adv_interval_t maxInterval = adv_interval_t(DEFAULT_ADVERTISING_INTERVAL_MAX),
139+
bool useLegacyPDU = true
133140
) :
134141
_advType(advType),
135142
_minInterval(minInterval),
@@ -147,27 +154,91 @@ class AdvertisingParameters {
147154
_channel39(true),
148155
_anonymous(false),
149156
_notifyOnScan(false),
150-
_legacyPDU(true),
157+
_legacyPDU(useLegacyPDU),
151158
_includeHeaderTxPower(false)
152159
{
153-
/* Min interval is slightly larger than in other modes. */
154-
if (_advType == advertising_type_t::NON_CONNECTABLE_UNDIRECTED) {
155-
_minInterval = adv_interval_t(std::max(_minInterval.value(), GAP_ADV_PARAMS_INTERVAL_MIN_NONCON));
156-
_maxInterval = adv_interval_t(std::max(_maxInterval.value(), GAP_ADV_PARAMS_INTERVAL_MIN_NONCON));
157-
}
160+
normalize();
161+
}
162+
163+
/**
164+
* Construct an instance of GapAdvertisingParams.
165+
*
166+
* @param[in] advType Type of advertising.
167+
* @param[in] useLegacyPDU If true legacy PDU shall be used for advertising.
168+
*
169+
* @note If CONNECTABLE_UNDIRECTED or CONNECTABLE_DIRECTED advertising is used
170+
* you must use legacy PDU.
171+
*
172+
* @note If type selected is incompatible with non legacy PDU, legacy PDU will be used.
173+
*/
174+
AdvertisingParameters(
175+
advertising_type_t advType,
176+
bool useLegacyPDU
177+
) :
178+
_advType(advType),
179+
_minInterval(adv_interval_t(DEFAULT_ADVERTISING_INTERVAL_MIN)),
180+
_maxInterval(adv_interval_t(DEFAULT_ADVERTISING_INTERVAL_MAX)),
181+
_peerAddressType(target_peer_address_type_t::PUBLIC),
182+
_ownAddressType(own_address_type_t::RANDOM),
183+
_policy(advertising_filter_policy_t::NO_FILTER),
184+
_primaryPhy(phy_t::LE_1M),
185+
_secondaryPhy(phy_t::LE_1M),
186+
_peerAddress(),
187+
_txPower(127),
188+
_maxSkip(0),
189+
_channel37(true),
190+
_channel38(true),
191+
_channel39(true),
192+
_anonymous(false),
193+
_notifyOnScan(false),
194+
_legacyPDU(useLegacyPDU),
195+
_includeHeaderTxPower(false)
196+
{
197+
normalize();
158198
}
159199

160200
public:
201+
/**
202+
* Update the advertising type and whether to use legacy PDU.
203+
*
204+
* @note If legacy PDU is not used then you cannot use
205+
* CONNECTABLE_UNDIRECTED nor CONNECTABLE_DIRECTED.
206+
*
207+
* @param[in] newAdvType The new advertising type.
208+
*
209+
* @param[in] legacy If true, legacy PDU will be used.
210+
*
211+
* @return reference to this object.
212+
*/
213+
AdvertisingParameters &setType(advertising_type_t newAdvType, bool legacy)
214+
{
215+
if (newAdvType == advertising_type_t::CONNECTABLE_UNDIRECTED ||
216+
newAdvType == advertising_type_t::CONNECTABLE_DIRECTED) {
217+
/* these types can only be used with legacy PDUs */
218+
MBED_ASSERT(legacy);
219+
}
220+
_advType = newAdvType;
221+
_legacyPDU = legacy;
222+
return *this;
223+
}
161224

162225
/**
163226
* Update the advertising type.
164227
*
228+
* @note If legacy PDU is not used then you cannot use
229+
* CONNECTABLE_UNDIRECTED nor CONNECTABLE_DIRECTED.
230+
*
165231
* @param[in] newAdvType The new advertising type.
166232
*
167233
* @return reference to this object.
168234
*/
169235
AdvertisingParameters &setType(advertising_type_t newAdvType)
170236
{
237+
if (newAdvType == advertising_type_t::CONNECTABLE_UNDIRECTED ||
238+
newAdvType == advertising_type_t::CONNECTABLE_DIRECTED) {
239+
/* these types can only be used with legacy PDUs */
240+
MBED_ASSERT(_legacyPDU);
241+
}
171242
_advType = newAdvType;
172243
return *this;
173244
}
@@ -448,10 +519,19 @@ class AdvertisingParameters {
448519
*
449520
* @param enable If true, legacy PDU will be used.
450521
*
522+
* @note If CONNECTABLE_UNDIRECTED or CONNECTABLE_DIRECTED advertising is used
523+
* you must use legacy PDU.
524+
*
451525
* @return A reference to this object.
452526
*/
453527
AdvertisingParameters &setUseLegacyPDU(bool enable = true)
454528
{
529+
if (!enable) {
530+
/* these types can only be used with legacy PDUs */
531+
MBED_ASSERT((_advType != advertising_type_t::CONNECTABLE_UNDIRECTED) &&
532+
(_advType != advertising_type_t::CONNECTABLE_DIRECTED));
533+
}
534+
455535
_legacyPDU = enable;
456536
return *this;
457537
}
@@ -490,6 +570,8 @@ class AdvertisingParameters {
490570
*
491571
* @param enable Advertising anonymous if true.
492572
*
573+
* @note You may not use anonymous advertising with periodic advertising on the same set.
574+
*
493575
* @return reference to this object.
494576
*/
495577
AdvertisingParameters &setAnonymousAdvertising(bool enable)
@@ -507,6 +589,23 @@ class AdvertisingParameters {
507589
return _anonymous;
508590
}
509591

592+
private:
593+
/**
594+
* Enforce limits on parameters.
595+
*/
596+
void normalize()
597+
{
598+
/* Min interval is slightly larger than in other modes. */
599+
if (_advType == advertising_type_t::NON_CONNECTABLE_UNDIRECTED) {
600+
_minInterval = adv_interval_t(std::max(_minInterval.value(), GAP_ADV_PARAMS_INTERVAL_MIN_NONCON));
601+
_maxInterval = adv_interval_t(std::max(_maxInterval.value(), GAP_ADV_PARAMS_INTERVAL_MIN_NONCON));
602+
}
603+
if (_advType == advertising_type_t::CONNECTABLE_DIRECTED ||
604+
_advType == advertising_type_t::CONNECTABLE_UNDIRECTED) {
605+
_legacyPDU = true;
606+
}
607+
}
608+
510609
private:
511610
advertising_type_t _advType;
512611
/* The advertising interval in ADV duration units (in other words, 0.625ms). */

features/FEATURE_BLE/ble/gap/Gap.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,18 @@ class Gap {
538538
*/
539539
virtual uint16_t getMaxAdvertisingDataLength();
540540

541+
/** Return maximum advertising data length supported for connectable advertising.
542+
*
543+
* @return Maximum advertising data length supported for connectable advertising.
544+
*/
545+
virtual uint16_t getMaxConnectableAdvertisingDataLength();
546+
547+
/** Return maximum advertising data length you may set if advertising set is active.
548+
*
549+
* @return Maximum advertising data length you may set if advertising set is active.
550+
*/
551+
virtual uint16_t getMaxActiveSetAdvertisingDataLength();
552+
541553
/** Create an advertising set and apply the passed in parameters. The handle returned
542554
* by this function must be used for all other calls that accept an advertising handle.
543555
* When done with advertising, remove from the system using destroyAdvertisingSet().
@@ -583,6 +595,10 @@ class Gap {
583595
* @param handle Advertising set handle.
584596
* @param payload Advertising payload.
585597
*
598+
* @note If advertising set is active you may only set payload of length equal or less
599+
* than getMaxActiveSetAdvertisingDataLength(). If you require a longer payload you must
600+
* stop the advertising set, set the payload and restart the set.
601+
*
586602
* @return BLE_ERROR_NONE on success.
587603
*
588604
* @see ble::AdvertisingDataBuilder to build a payload.
@@ -598,6 +614,10 @@ class Gap {
598614
* @param handle Advertising set handle.
599615
* @param response Advertising scan response.
600616
*
617+
* @note If advertising set is active you may only set payload of length equal or less
618+
* than getMaxActiveSetAdvertisingDataLength(). If you require a longer payload you must
619+
* stop the advertising set, set the payload and restart the set.
620+
*
601621
* @return BLE_ERROR_NONE on success.
602622
*
603623
* @see ble::AdvertisingDataBuilder to build a payload.
@@ -663,6 +683,11 @@ class Gap {
663683
* @param payload Advertising payload.
664684
* @return BLE_ERROR_NONE on success.
665685
*
686+
* @note If advertising set is active you may only set payload of length equal or less
687+
* than getMaxActiveSetAdvertisingDataLength(). If you require a longer payload you must
688+
* stop the advertising set, set the payload and restart the set. Stopping the set will
689+
* cause peers to lose sync on the periodic set.
690+
*
666691
* @see ble::AdvertisingDataBuilder to build a payload.
667692
*
668693
* @version 5+

features/FEATURE_BLE/ble/generic/GenericGap.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ class GenericGap :
5050
public:
5151
/* TODO: move to config */
5252
static const uint8_t MAX_ADVERTISING_SETS = 15;
53-
static const size_t MAX_HCI_DATA_LENGTH = 251;
5453

5554
/**
5655
* Construct a GenericGap.
@@ -92,6 +91,14 @@ class GenericGap :
9291
*/
9392
virtual uint16_t getMaxAdvertisingDataLength();
9493

94+
/** @copydoc Gap::getMaxConnectableAdvertisingDataLength
95+
*/
96+
virtual uint16_t getMaxConnectableAdvertisingDataLength();
97+
98+
/** @copydoc Gap::getMaxActiveSetAdvertisingDataLength
99+
*/
100+
virtual uint16_t getMaxActiveSetAdvertisingDataLength();
101+
95102
/** @copydoc Gap::createAdvertisingSet
96103
*/
97104
virtual ble_error_t createAdvertisingSet(
@@ -781,6 +788,8 @@ class GenericGap :
781788
BitArray<MAX_ADVERTISING_SETS> _existing_sets;
782789
BitArray<MAX_ADVERTISING_SETS> _active_sets;
783790
BitArray<MAX_ADVERTISING_SETS> _active_periodic_sets;
791+
BitArray<MAX_ADVERTISING_SETS> _connectable_payload_size_exceeded;
792+
BitArray<MAX_ADVERTISING_SETS> _set_is_connectable;
784793

785794
// deprecation flags
786795
mutable bool _deprecated_scan_api_used : 1;

features/FEATURE_BLE/ble/pal/PalGap.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,23 @@ struct Gap {
764764
*/
765765
virtual uint16_t get_maximum_advertising_data_length() = 0;
766766

767+
/**
768+
* Query the maximum data length the controller supports in an advertising set
769+
* using connectable advertising.
770+
*
771+
* @return The length in byte the controller can support in an advertising set
772+
* for connectable advertising.
773+
*/
774+
virtual uint16_t get_maximum_connectable_advertising_data_length() = 0;
775+
776+
/**
777+
* Query the maximum payload length for a single HCI packet carrying partial
778+
* (or complete if it fits) data for advertising set.
779+
*
780+
* @return Max size of the HCI packet transporting the data.
781+
*/
782+
virtual uint8_t get_maximum_hci_advertising_data_length() = 0;
783+
767784
/**
768785
* Query the maximum number of concurrent advertising sets that is supported
769786
* by the controller.

features/FEATURE_BLE/source/gap/Gap.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,18 @@ uint16_t Gap::getMaxAdvertisingDataLength()
3636
return LEGACY_ADVERTISING_MAX_SIZE;
3737
}
3838

39+
uint16_t Gap::getMaxConnectableAdvertisingDataLength()
40+
{
41+
/* Requesting action from porter(s): override this API if this capability is supported. */
42+
return LEGACY_ADVERTISING_MAX_SIZE;
43+
}
44+
45+
uint16_t Gap::getMaxActiveSetAdvertisingDataLength()
46+
{
47+
/* Requesting action from porter(s): override this API if this capability is supported. */
48+
return LEGACY_ADVERTISING_MAX_SIZE;
49+
}
50+
3951
ble_error_t Gap::createAdvertisingSet(
4052
advertising_handle_t *handle,
4153
const AdvertisingParameters &parameters

0 commit comments

Comments
 (0)