Bluetooth: controller: split: Add AuxPtr to ADV_EXT_IND PDU

Add implementation to support ADV_EXT_IND PDU with AuxPtr.
Changes in this commit only prepares the ADV_EXT_IND PDU
in the primary channel.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2020-01-27 17:17:46 +05:30 committed by Carles Cufí
commit fdd91bb116
3 changed files with 161 additions and 11 deletions

View file

@ -191,7 +191,7 @@ uint8_t ll_adv_params_set(uint16_t interval, uint8_t adv_type,
#if defined(CONFIG_BT_CTLR_ADV_EXT)
} else if (pdu->type == PDU_ADV_TYPE_EXT_IND) {
struct pdu_adv_com_ext_adv *p;
struct ext_adv_hdr _h, *h;
struct ext_adv_hdr *h, _h;
uint8_t *_ptr, *ptr;
uint8_t len;
@ -222,7 +222,10 @@ uint8_t ll_adv_params_set(uint16_t interval, uint8_t adv_type,
ptr += BDADDR_SIZE;
}
/* TODO: TargetA flag */
/* TODO: TargetA flag in primary channel PDU only for directed
*/
/* No CTEInfo flag in primary channel PDU */
/* ADI flag */
if (_h.adi) {
@ -239,6 +242,9 @@ uint8_t ll_adv_params_set(uint16_t interval, uint8_t adv_type,
/* No SyncInfo flag in primary channel PDU */
/* Tx Power flag */
/* C1, Tx Power is optional on the LE 1M PHY, and reserved for
* for future use on the LE Coded PHY.
*/
if (evt_prop & BIT(6) &&
(!_h.aux_ptr || (phy_p != BIT(2)))) {
h->tx_pwr = 1;
@ -295,18 +301,23 @@ uint8_t ll_adv_params_set(uint16_t interval, uint8_t adv_type,
aux = (void *)ptr;
aux->phy = find_lsb_set(phy_s);
}
adv->phy_s = phy_s;
/* ADI */
if (h->adi) {
struct ext_adv_adi *adi;
ptr -= sizeof(struct ext_adv_adi);
/* NOTE: memcpy shall handle overlapping buffers */
memcpy(ptr, _ptr, sizeof(struct ext_adv_adi));
adi = (void *)ptr;
adi->sid = sid;
}
adv->sid = sid;
/* No CTEInfo field in primary channel PDU */
/* NOTE: TargetA, filled at enable and RPA timeout */

View file

@ -37,36 +37,173 @@ uint8_t *ll_adv_aux_random_addr_get(uint8_t handle, uint8_t *addr)
uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, uint8_t len,
uint8_t *data)
{
struct pdu_adv_com_ext_adv *p;
struct pdu_adv_com_ext_adv *p, *_p;
struct ext_adv_hdr *h, _h;
struct ll_adv_set *adv;
struct ext_adv_hdr *h;
uint8_t pdu_len, _pdu_len;
struct pdu_adv *prev;
struct pdu_adv *pdu;
uint8_t *_ptr, *ptr;
uint8_t idx;
/* TODO: */
/* op param definitions:
* 0x00 - Intermediate fragment of fragmented extended advertising data
* 0x01 - First fragment of fragmented extended advertising data
* 0x02 - Last fragemnt of fragemented extended advertising data
* 0x03 - Complete extended advertising data
* 0x04 - Unchanged data (just update the advertising data)
* All other values, Reserved for future use
*/
/* TODO: handle other op values */
if ((op != 0x03) && (op != 0x04)) {
/* FIXME: error code */
return BT_HCI_ERR_CMD_DISALLOWED;
}
/* Get the advertising set instance */
adv = ull_adv_set_get(handle);
if (!adv) {
return BT_HCI_ERR_CMD_DISALLOWED;
}
/* Dont update data if not extended advertising. */
/* Do not update data if not extended advertising. */
prev = lll_adv_data_peek(&adv->lll);
if (prev->type != PDU_ADV_TYPE_EXT_IND) {
return 0;
/* Advertising Handle has not been created using
* Set Extended Advertising Parameter command
*/
return BT_HCI_ERR_CMD_DISALLOWED;
}
/* Get reference to previous PDU data */
_p = (void *)&prev->adv_ext_ind;
h = (void *)_p->ext_hdr_adi_adv_data;
*(uint8_t *)&_h = *(uint8_t *)h;
_ptr = (uint8_t *)h + sizeof(*h);
/* Get reference new PDU data buffer */
pdu = lll_adv_data_alloc(&adv->lll, &idx);
p = (void *)&pdu->adv_ext_ind;
p->adv_mode = _p->adv_mode;
h = (void *)p->ext_hdr_adi_adv_data;
ptr = (uint8_t *)h + sizeof(*h);
*(uint8_t *)h = 0;
if (!h->aux_ptr) {
if (!len) {
return 0;
/* AdvA flag */
if (_h.adv_addr) {
_ptr += BDADDR_SIZE;
}
/* NOTE: as we will use auxiliary packet, we remove AdvA in primary
* channel. i.e. Do nothing to add AdvA in the new PDU.
*/
/* No TargetA in primary channel for undirected */
/* No CTEInfo flag in primary channel PDU */
/* ADI flag */
if (_h.adi) {
_ptr += sizeof(struct ext_adv_adi);
}
h->adi = 1;
ptr += sizeof(struct ext_adv_adi);
/* AuxPtr flag */
if (_h.aux_ptr) {
_ptr += sizeof(struct ext_adv_aux_ptr);
}
h->aux_ptr = 1;
ptr += sizeof(struct ext_adv_aux_ptr);
/* No SyncInfo flag in primary channel PDU */
/* Tx Power flag */
if (_h.tx_pwr) {
_ptr++;
/* C1, Tx Power is optional on the LE 1M PHY, and reserved for
* for future use on the LE Coded PHY.
*/
if (adv->lll.phy_p != BIT(2)) {
h->tx_pwr = 1;
ptr++;
}
}
/* Calc primary PDU len */
_pdu_len = _ptr - (uint8_t *)_p;
pdu_len = ptr - (uint8_t *)p;
p->ext_hdr_len = pdu_len - offsetof(struct pdu_adv_com_ext_adv,
ext_hdr_adi_adv_data);
pdu->len = pdu_len;
/* Start filling primary PDU payload based on flags */
/* No AdvData in primary channel PDU */
/* No ACAD in primary channel PDU */
/* Tx Power */
if (h->tx_pwr) {
*--ptr = *--_ptr;
}
/* No SyncInfo in primary channel PDU */
/* AuxPtr */
if (_h.aux_ptr) {
_ptr -= sizeof(struct ext_adv_aux_ptr);
}
{
struct ext_adv_aux_ptr *aux;
ptr -= sizeof(struct ext_adv_aux_ptr);
/* NOTE: Channel Index, CA, Offset Units and AUX Offset will be
* set in Advertiser Event.
*/
aux = (void *)ptr;
aux->phy = find_lsb_set(adv->phy_s);
}
/* ADI */
{
struct ext_adv_adi *adi;
uint16_t did = UINT16_MAX;
ptr -= sizeof(struct ext_adv_adi);
adi = (void *)ptr;
if (_h.adi) {
struct ext_adv_adi *_adi;
_ptr -= sizeof(struct ext_adv_adi);
/* NOTE: memcpy shall handle overlapping buffers */
memcpy(ptr, _ptr, sizeof(struct ext_adv_adi));
_adi = (void *)_ptr;
did = _adi->did;
} else {
adi->sid = adv->sid;
}
if ((op == 0x04) || len || (_pdu_len != pdu_len)) {
did++;
}
adi->did = did;
}
/* No CTEInfo field in primary channel PDU */
/* NOTE: TargetA, filled at enable and RPA timeout */
/* No AdvA in primary channel due to AuxPtr being added */
lll_adv_data_enqueue(&adv->lll, idx);
return 0;

View file

@ -9,8 +9,6 @@ struct ll_adv_set {
struct ull_hdr ull;
struct lll_adv lll;
uint8_t is_enabled:1;
#if defined(CONFIG_BT_PERIPHERAL)
memq_link_t *link_cc_free;
struct node_rx_pdu *node_rx_cc_free;
@ -18,10 +16,14 @@ struct ll_adv_set {
#if defined(CONFIG_BT_CTLR_ADV_EXT)
uint32_t interval;
uint8_t sid:4;
uint8_t phy_s:3;
#else /* !CONFIG_BT_CTLR_ADV_EXT */
uint16_t interval;
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
uint8_t is_enabled:1;
#if defined(CONFIG_BT_CTLR_PRIVACY)
uint8_t own_addr_type:2;
uint8_t id_addr_type:1;