Skip to content

Commit d84c549

Browse files
cvinayakcarlescufi
authored andcommitted
Bluetooth: Controller: Add Extended Advertising Type Validations
Add Extended Advertising Type validation when associated Periodic Advertising is enable, and Extended Advertising set is re-configured to other advertising types. Signed-off-by: Vinayak Kariappa Chettimada <[email protected]>
1 parent 364a8c2 commit d84c549

File tree

2 files changed

+117
-17
lines changed

2 files changed

+117
-17
lines changed

subsys/bluetooth/controller/ll_sw/ull_adv.c

Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ static void conn_release(struct ll_adv_set *adv);
9191
#endif /* CONFIG_BT_PERIPHERAL */
9292

9393
#if defined(CONFIG_BT_CTLR_ADV_EXT)
94+
static uint8_t leg_adv_type_get(uint8_t evt_prop);
9495
static void adv_max_events_duration_set(struct ll_adv_set *adv,
9596
uint16_t duration,
9697
uint8_t max_ext_adv_evts);
@@ -255,24 +256,25 @@ uint8_t ll_adv_params_set(uint16_t interval, uint8_t adv_type,
255256
if (adv_type == PDU_ADV_TYPE_EXT_IND) {
256257
/* legacy */
257258
if (evt_prop & BT_HCI_LE_ADV_PROP_LEGACY) {
258-
/* lookup evt_prop to PDU type in pdu_adv_type[] */
259-
uint8_t const leg_adv_type[] = {
260-
0x03, /* PDU_ADV_TYPE_NONCONN_IND */
261-
0x04, /* PDU_ADV_TYPE_DIRECT_IND */
262-
0x02, /* PDU_ADV_TYPE_SCAN_IND */
263-
0x00 /* PDU_ADV_TYPE_ADV_IND */
264-
};
265-
266259
if (evt_prop & BT_HCI_LE_ADV_PROP_ANON) {
267260
return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
268261
}
269262

270-
adv_type = leg_adv_type[evt_prop & 0x03];
263+
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
264+
/* disallow changing to legacy advertising while
265+
* periodic advertising enabled.
266+
*/
267+
if (adv->lll.sync) {
268+
const struct ll_adv_sync_set *sync;
271269

272-
/* high duty cycle directed */
273-
if (evt_prop & BT_HCI_LE_ADV_PROP_HI_DC_CONN) {
274-
adv_type = 0x01; /* PDU_ADV_TYPE_DIRECT_IND */
270+
sync = HDR_LLL2ULL(adv->lll.sync);
271+
if (sync->is_enabled) {
272+
return BT_HCI_ERR_INVALID_PARAM;
273+
}
275274
}
275+
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
276+
277+
adv_type = leg_adv_type_get(evt_prop);
276278

277279
adv->lll.phy_p = PHY_1M;
278280
} else {
@@ -287,6 +289,20 @@ uint8_t ll_adv_params_set(uint16_t interval, uint8_t adv_type,
287289
return BT_HCI_ERR_INVALID_PARAM;
288290
}
289291

292+
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
293+
if (adv->lll.sync &&
294+
(evt_prop & (BT_HCI_LE_ADV_PROP_ANON |
295+
BT_HCI_LE_ADV_PROP_CONN |
296+
BT_HCI_LE_ADV_PROP_SCAN))) {
297+
const struct ll_adv_sync_set *sync;
298+
299+
sync = HDR_LLL2ULL(adv->lll.sync);
300+
if (sync->is_enabled) {
301+
return BT_HCI_ERR_INVALID_PARAM;
302+
}
303+
}
304+
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
305+
290306
#if (CONFIG_BT_CTLR_ADV_AUX_SET == 0)
291307
/* Connectable or scannable requires aux */
292308
if (evt_prop & (BT_HCI_LE_ADV_PROP_CONN |
@@ -295,8 +311,8 @@ uint8_t ll_adv_params_set(uint16_t interval, uint8_t adv_type,
295311
}
296312
#endif
297313

298-
adv_type = 0x05; /* PDU_ADV_TYPE_EXT_IND in */
299-
/* pdu_adv_type array. */
314+
adv_type = 0x05; /* index of PDU_ADV_TYPE_EXT_IND in */
315+
/* pdu_adv_type[] */
300316

301317
adv->lll.phy_p = phy_p;
302318
adv->lll.phy_flags = PHY_FLAGS_S8;
@@ -463,9 +479,8 @@ uint8_t ll_adv_params_set(uint16_t interval, uint8_t adv_type,
463479
pri_dptr_prev += BDADDR_SIZE;
464480
}
465481
if (!pri_com_hdr->adv_mode &&
466-
(!pri_hdr_prev.aux_ptr ||
467-
(!(evt_prop & BT_HCI_LE_ADV_PROP_ANON) &&
468-
(phy_p != PHY_CODED)))) {
482+
!(evt_prop & BT_HCI_LE_ADV_PROP_ANON) &&
483+
(!pri_hdr_prev.aux_ptr || (phy_p != PHY_CODED))) {
469484
/* TODO: optional on 1M with Aux Ptr */
470485
pri_hdr->adv_addr = 1;
471486

@@ -2421,6 +2436,28 @@ static void conn_release(struct ll_adv_set *adv)
24212436
#endif /* CONFIG_BT_PERIPHERAL */
24222437

24232438
#if defined(CONFIG_BT_CTLR_ADV_EXT)
2439+
static uint8_t leg_adv_type_get(uint8_t evt_prop)
2440+
{
2441+
/* We take advantage of the fact that 2 LS bits
2442+
* of evt_prop can be used in a lookup to return
2443+
* PDU type value in the pdu_adv_type[] lookup.
2444+
*/
2445+
uint8_t const leg_adv_type[] = {
2446+
0x03, /* index of PDU_ADV_TYPE_NONCONN_IND in pdu_adv_type[] */
2447+
0x04, /* index of PDU_ADV_TYPE_DIRECT_IND in pdu_adv_type[] */
2448+
0x02, /* index of PDU_ADV_TYPE_SCAN_IND in pdu_adv_type[] */
2449+
0x00 /* index of PDU_ADV_TYPE_ADV_IND in pdu_adv_type[] */
2450+
};
2451+
2452+
/* if high duty cycle directed */
2453+
if (evt_prop & BT_HCI_LE_ADV_PROP_HI_DC_CONN) {
2454+
/* index of PDU_ADV_TYPE_DIRECT_IND in pdu_adv_type[] */
2455+
return 0x01;
2456+
}
2457+
2458+
return leg_adv_type[evt_prop & 0x03];
2459+
}
2460+
24242461
static void adv_max_events_duration_set(struct ll_adv_set *adv,
24252462
uint16_t duration,
24262463
uint8_t max_ext_adv_evts)

subsys/bluetooth/controller/ll_sw/ull_adv_sync.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include "hal/debug.h"
4949

5050
static int init_reset(void);
51+
static uint8_t adv_type_check(struct ll_adv_set *adv);
5152
static inline struct ll_adv_sync_set *sync_acquire(void);
5253
static inline void sync_release(struct ll_adv_sync_set *sync);
5354
static inline uint16_t sync_handle_get(struct ll_adv_sync_set *sync);
@@ -350,6 +351,15 @@ uint8_t ll_adv_sync_param_set(uint8_t handle, uint16_t interval, uint16_t flags)
350351
return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
351352
}
352353

354+
if (IS_ENABLED(CONFIG_BT_CTLR_PARAM_CHECK)) {
355+
uint8_t err;
356+
357+
err = adv_type_check(adv);
358+
if (err) {
359+
return err;
360+
}
361+
}
362+
353363
lll_sync = adv->lll.sync;
354364
if (!lll_sync) {
355365
struct pdu_adv *ter_pdu;
@@ -455,6 +465,15 @@ uint8_t ll_adv_sync_ad_data_set(uint8_t handle, uint8_t op, uint8_t len,
455465
return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
456466
}
457467

468+
if (IS_ENABLED(CONFIG_BT_CTLR_PARAM_CHECK)) {
469+
uint8_t err;
470+
471+
err = adv_type_check(adv);
472+
if (err) {
473+
return err;
474+
}
475+
}
476+
458477
lll_sync = adv->lll.sync;
459478
if (!lll_sync) {
460479
return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
@@ -587,6 +606,15 @@ uint8_t ll_adv_sync_enable(uint8_t handle, uint8_t enable)
587606
return err;
588607
}
589608

609+
if (IS_ENABLED(CONFIG_BT_CTLR_PARAM_CHECK)) {
610+
uint8_t err;
611+
612+
err = adv_type_check(adv);
613+
if (err) {
614+
return BT_HCI_ERR_CMD_DISALLOWED;
615+
}
616+
}
617+
590618
/* TODO: Check for periodic data being complete */
591619

592620
/* TODO: Check packet too long */
@@ -1516,6 +1544,41 @@ static int init_reset(void)
15161544
return 0;
15171545
}
15181546

1547+
static uint8_t adv_type_check(struct ll_adv_set *adv)
1548+
{
1549+
struct pdu_adv_com_ext_adv *pri_com_hdr;
1550+
struct pdu_adv_ext_hdr *pri_hdr;
1551+
struct pdu_adv *pri_pdu;
1552+
1553+
pri_pdu = lll_adv_data_latest_peek(&adv->lll);
1554+
if (pri_pdu->type != PDU_ADV_TYPE_EXT_IND) {
1555+
return BT_HCI_ERR_INVALID_PARAM;
1556+
}
1557+
1558+
pri_com_hdr = (void *)&pri_pdu->adv_ext_ind;
1559+
if (pri_com_hdr->adv_mode != 0U) {
1560+
return BT_HCI_ERR_INVALID_PARAM;
1561+
}
1562+
1563+
pri_hdr = (void *)pri_com_hdr->ext_hdr_adv_data;
1564+
if (pri_hdr->aux_ptr) {
1565+
struct pdu_adv_com_ext_adv *sec_com_hdr;
1566+
struct pdu_adv_ext_hdr *sec_hdr;
1567+
struct pdu_adv *sec_pdu;
1568+
1569+
sec_pdu = lll_adv_aux_data_latest_peek(adv->lll.aux);
1570+
sec_com_hdr = (void *)&sec_pdu->adv_ext_ind;
1571+
sec_hdr = (void *)sec_com_hdr->ext_hdr_adv_data;
1572+
if (!pri_hdr->adv_addr && !sec_hdr->adv_addr) {
1573+
return BT_HCI_ERR_INVALID_PARAM;
1574+
}
1575+
} else if (!pri_hdr->adv_addr) {
1576+
return BT_HCI_ERR_INVALID_PARAM;
1577+
}
1578+
1579+
return 0;
1580+
}
1581+
15191582
static inline struct ll_adv_sync_set *sync_acquire(void)
15201583
{
15211584
return mem_acquire(&adv_sync_free);

0 commit comments

Comments
 (0)