Bluetooth: controller: Fix TxAdd setting in auxiliary PDU

When controller is built with extended advertising support but without
LL Privacy build fails due to issue with code that sets TxAdd in aux
PDU:

.../ll_sw/ull_adv_aux.c: In function 'ull_adv_aux_hdr_set_clear':
.../ll_sw/ull_adv_aux.c:502:25: error: 'struct ll_adv_set' has no
                                member named 'own_addr_type'
  502 |   sec_pdu->tx_addr = adv->own_addr_type & 0x1;
      |

We need own_addr_type value if an advertising set with aux but without
AD is created since we cannot get TxAdd value from other PDU.

ull_adv_aux_hdr_set_clear() can now be called with a flag to explicitly
set AdvA field and pass own_addr_type in 'value' parameter. This allows
to set proper TxAdd when creating new advertising set.

On aux updates, we use TxAdd from other PDU:
- if primary PDU has AdvA, we use TxAdd from that PDU
- if previous secundary PDU has AdvA, we use TxAdd from that PDU
In other case we just return an unpsecified error since this should not
happen in any valid scenario.

Signed-off-by: Andrzej Kaczmarek <andrzej.kaczmarek@codecoup.pl>
This commit is contained in:
Andrzej Kaczmarek 2020-09-09 14:20:25 +02:00 committed by Carles Cufí
commit 7a113ea657
3 changed files with 28 additions and 17 deletions

View file

@ -482,7 +482,10 @@ uint8_t ll_adv_params_set(uint16_t interval, uint8_t adv_type,
if (pri_hdr->aux_ptr) {
uint8_t err;
err = ull_adv_aux_hdr_set_clear(adv, 0, 0, NULL, NULL);
err = ull_adv_aux_hdr_set_clear(adv,
ULL_ADV_PDU_HDR_FIELD_ADVA,
0, &own_addr_type,
NULL);
if (err) {
/* TODO: cleanup? */
return err;

View file

@ -395,6 +395,10 @@ uint8_t ull_adv_aux_hdr_set_clear(struct ll_adv_set *adv,
lll = &adv->lll;
/* Can't have both flags set here since both use 'value' extra param */
LL_ASSERT(!(sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ADVA) ||
!(sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA));
/* Get reference to previous primary PDU data */
pri_pdu_prev = lll_adv_data_peek(lll);
if (pri_pdu_prev->type != PDU_ADV_TYPE_EXT_IND) {
@ -485,32 +489,35 @@ uint8_t ull_adv_aux_hdr_set_clear(struct ll_adv_set *adv,
*(uint8_t *)sec_hdr = 0U;
/* AdvA flag */
/* NOTE: as we will use auxiliary packet, we remove AdvA in
* primary channel. i.e. Do nothing to not add AdvA in the primary
* PDU. Connectable or scannable advertising always has AdvA in aux.
/* NOTE: as we will use auxiliary packet, we remove AdvA in primary
* channel, i.e. do nothing to not add AdvA in the primary PDU.
* AdvA can be either set explicitly (i.e. needs own_addr_type to be
* set), can be copied from primary PDU (i.e. adding AD to existing set)
* or can be copied from previous secondary PDU.
*/
if (pri_hdr_prev.adv_addr) {
pri_dptr_prev += BDADDR_SIZE;
sec_hdr->adv_addr = 1;
if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ADVA) {
uint8_t own_addr_type = *(uint8_t *)value;
/* Prepare to add AdvA in secondary PDU */
sec_hdr->adv_addr = 1;
/* NOTE: AdvA is filled at enable */
sec_pdu->tx_addr = own_addr_type & 0x1;
} else if (pri_hdr_prev.adv_addr) {
sec_pdu->tx_addr = pri_pdu->tx_addr;
} else if (pri_com_hdr->adv_mode) {
sec_hdr->adv_addr = 1;
sec_pdu->tx_addr = adv->own_addr_type & 0x1;
} else if (sec_hdr_prev.adv_addr) {
sec_pdu->tx_addr = sec_pdu_prev->tx_addr;
} else {
/* We do not have valid address info, this should not happen */
return BT_HCI_ERR_UNSPECIFIED;
}
pri_pdu->tx_addr = 0U;
pri_pdu->rx_addr = 0U;
if (pri_hdr_prev.adv_addr) {
pri_dptr_prev += BDADDR_SIZE;
}
if (sec_hdr_prev.adv_addr) {
sec_dptr_prev += BDADDR_SIZE;
sec_hdr->adv_addr = 1;
}
if (sec_hdr->adv_addr) {
sec_dptr += BDADDR_SIZE;
}
sec_dptr += BDADDR_SIZE;
/* No TargetA in primary and secondary channel for undirected */
/* No CTEInfo flag in primary and secondary channel PDU */

View file

@ -48,6 +48,7 @@ uint8_t ull_scan_rsp_set(struct ll_adv_set *adv, uint8_t len,
#if defined(CONFIG_BT_CTLR_ADV_EXT)
#define ULL_ADV_PDU_HDR_FIELD_ADVA BIT(0)
#define ULL_ADV_PDU_HDR_FIELD_SYNC_INFO BIT(5)
#define ULL_ADV_PDU_HDR_FIELD_AD_DATA BIT(8)