Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 54 additions & 17 deletions subsys/bluetooth/controller/ll_sw/ull_adv.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ static void conn_release(struct ll_adv_set *adv);
#endif /* CONFIG_BT_PERIPHERAL */

#if defined(CONFIG_BT_CTLR_ADV_EXT)
static uint8_t leg_adv_type_get(uint8_t evt_prop);
static void adv_max_events_duration_set(struct ll_adv_set *adv,
uint16_t duration,
uint8_t max_ext_adv_evts);
Expand Down Expand Up @@ -255,24 +256,25 @@ uint8_t ll_adv_params_set(uint16_t interval, uint8_t adv_type,
if (adv_type == PDU_ADV_TYPE_EXT_IND) {
/* legacy */
if (evt_prop & BT_HCI_LE_ADV_PROP_LEGACY) {
/* lookup evt_prop to PDU type in pdu_adv_type[] */
uint8_t const leg_adv_type[] = {
0x03, /* PDU_ADV_TYPE_NONCONN_IND */
0x04, /* PDU_ADV_TYPE_DIRECT_IND */
0x02, /* PDU_ADV_TYPE_SCAN_IND */
0x00 /* PDU_ADV_TYPE_ADV_IND */
};

if (evt_prop & BT_HCI_LE_ADV_PROP_ANON) {
return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
}

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

/* high duty cycle directed */
if (evt_prop & BT_HCI_LE_ADV_PROP_HI_DC_CONN) {
adv_type = 0x01; /* PDU_ADV_TYPE_DIRECT_IND */
sync = HDR_LLL2ULL(adv->lll.sync);
if (sync->is_enabled) {
return BT_HCI_ERR_INVALID_PARAM;
}
}
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */

adv_type = leg_adv_type_get(evt_prop);

adv->lll.phy_p = PHY_1M;
} else {
Expand All @@ -287,6 +289,20 @@ uint8_t ll_adv_params_set(uint16_t interval, uint8_t adv_type,
return BT_HCI_ERR_INVALID_PARAM;
}

#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
if (adv->lll.sync &&
(evt_prop & (BT_HCI_LE_ADV_PROP_ANON |
BT_HCI_LE_ADV_PROP_CONN |
BT_HCI_LE_ADV_PROP_SCAN))) {
const struct ll_adv_sync_set *sync;

sync = HDR_LLL2ULL(adv->lll.sync);
if (sync->is_enabled) {
return BT_HCI_ERR_INVALID_PARAM;
}
}
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */

#if (CONFIG_BT_CTLR_ADV_AUX_SET == 0)
/* Connectable or scannable requires aux */
if (evt_prop & (BT_HCI_LE_ADV_PROP_CONN |
Expand All @@ -295,8 +311,8 @@ uint8_t ll_adv_params_set(uint16_t interval, uint8_t adv_type,
}
#endif

adv_type = 0x05; /* PDU_ADV_TYPE_EXT_IND in */
/* pdu_adv_type array. */
adv_type = 0x05; /* index of PDU_ADV_TYPE_EXT_IND in */
/* pdu_adv_type[] */

adv->lll.phy_p = phy_p;
adv->lll.phy_flags = PHY_FLAGS_S8;
Expand Down Expand Up @@ -463,9 +479,8 @@ uint8_t ll_adv_params_set(uint16_t interval, uint8_t adv_type,
pri_dptr_prev += BDADDR_SIZE;
}
if (!pri_com_hdr->adv_mode &&
(!pri_hdr_prev.aux_ptr ||
(!(evt_prop & BT_HCI_LE_ADV_PROP_ANON) &&
(phy_p != PHY_CODED)))) {
!(evt_prop & BT_HCI_LE_ADV_PROP_ANON) &&
(!pri_hdr_prev.aux_ptr || (phy_p != PHY_CODED))) {
/* TODO: optional on 1M with Aux Ptr */
pri_hdr->adv_addr = 1;

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

#if defined(CONFIG_BT_CTLR_ADV_EXT)
static uint8_t leg_adv_type_get(uint8_t evt_prop)
{
/* We take advantage of the fact that 2 LS bits
* of evt_prop can be used in a lookup to return
* PDU type value in the pdu_adv_type[] lookup.
*/
uint8_t const leg_adv_type[] = {
0x03, /* index of PDU_ADV_TYPE_NONCONN_IND in pdu_adv_type[] */
0x04, /* index of PDU_ADV_TYPE_DIRECT_IND in pdu_adv_type[] */
0x02, /* index of PDU_ADV_TYPE_SCAN_IND in pdu_adv_type[] */
0x00 /* index of PDU_ADV_TYPE_ADV_IND in pdu_adv_type[] */
};

/* if high duty cycle directed */
if (evt_prop & BT_HCI_LE_ADV_PROP_HI_DC_CONN) {
/* index of PDU_ADV_TYPE_DIRECT_IND in pdu_adv_type[] */
return 0x01;
}

return leg_adv_type[evt_prop & 0x03];
}

static void adv_max_events_duration_set(struct ll_adv_set *adv,
uint16_t duration,
uint8_t max_ext_adv_evts)
Expand Down
63 changes: 63 additions & 0 deletions subsys/bluetooth/controller/ll_sw/ull_adv_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
#include "hal/debug.h"

static int init_reset(void);
static uint8_t adv_type_check(struct ll_adv_set *adv);
static inline struct ll_adv_sync_set *sync_acquire(void);
static inline void sync_release(struct ll_adv_sync_set *sync);
static inline uint16_t sync_handle_get(struct ll_adv_sync_set *sync);
Expand Down Expand Up @@ -350,6 +351,15 @@ uint8_t ll_adv_sync_param_set(uint8_t handle, uint16_t interval, uint16_t flags)
return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
}

if (IS_ENABLED(CONFIG_BT_CTLR_PARAM_CHECK)) {
uint8_t err;

err = adv_type_check(adv);
if (err) {
return err;
}
}

lll_sync = adv->lll.sync;
if (!lll_sync) {
struct pdu_adv *ter_pdu;
Expand Down Expand Up @@ -455,6 +465,15 @@ uint8_t ll_adv_sync_ad_data_set(uint8_t handle, uint8_t op, uint8_t len,
return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
}

if (IS_ENABLED(CONFIG_BT_CTLR_PARAM_CHECK)) {
uint8_t err;

err = adv_type_check(adv);
if (err) {
return err;
}
}

lll_sync = adv->lll.sync;
if (!lll_sync) {
return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
Expand Down Expand Up @@ -549,6 +568,15 @@ uint8_t ll_adv_sync_enable(uint8_t handle, uint8_t enable)
return err;
}

if (IS_ENABLED(CONFIG_BT_CTLR_PARAM_CHECK)) {
uint8_t err;

err = adv_type_check(adv);
if (err) {
return BT_HCI_ERR_CMD_DISALLOWED;
}
}

/* TODO: Check for periodic data being complete */

/* TODO: Check packet too long */
Expand Down Expand Up @@ -1454,6 +1482,41 @@ static int init_reset(void)
return 0;
}

static uint8_t adv_type_check(struct ll_adv_set *adv)
{
struct pdu_adv_com_ext_adv *pri_com_hdr;
struct pdu_adv_ext_hdr *pri_hdr;
struct pdu_adv *pri_pdu;

pri_pdu = lll_adv_data_latest_peek(&adv->lll);
if (pri_pdu->type != PDU_ADV_TYPE_EXT_IND) {
return BT_HCI_ERR_INVALID_PARAM;
}

pri_com_hdr = (void *)&pri_pdu->adv_ext_ind;
if (pri_com_hdr->adv_mode != 0U) {
return BT_HCI_ERR_INVALID_PARAM;
}

pri_hdr = (void *)pri_com_hdr->ext_hdr_adv_data;
if (pri_hdr->aux_ptr) {
struct pdu_adv_com_ext_adv *sec_com_hdr;
struct pdu_adv_ext_hdr *sec_hdr;
struct pdu_adv *sec_pdu;

sec_pdu = lll_adv_aux_data_latest_peek(adv->lll.aux);
sec_com_hdr = (void *)&sec_pdu->adv_ext_ind;
sec_hdr = (void *)sec_com_hdr->ext_hdr_adv_data;
if (!pri_hdr->adv_addr && !sec_hdr->adv_addr) {
return BT_HCI_ERR_INVALID_PARAM;
}
} else if (!pri_hdr->adv_addr) {
return BT_HCI_ERR_INVALID_PARAM;
}

return 0;
}

static inline struct ll_adv_sync_set *sync_acquire(void)
{
return mem_acquire(&adv_sync_free);
Expand Down