Skip to content

Commit 001d902

Browse files
Bluetooth: Controller: Rework support for periodic adv reports
Periodic advertising PDUs are now dispatched immediately one by one (i.e. without list of PDUs as when flushed from aux context) so we do not need to iterate such a list. Signed-off-by: Andrzej Kaczmarek <[email protected]>
1 parent dfa6344 commit 001d902

File tree

6 files changed

+141
-181
lines changed

6 files changed

+141
-181
lines changed

subsys/bluetooth/controller/hci/hci.c

Lines changed: 124 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -5523,232 +5523,190 @@ static void le_per_adv_sync_report(struct pdu_data *pdu_data,
55235523
struct net_buf *buf)
55245524
{
55255525
struct bt_hci_evt_le_per_advertising_report *sep;
5526+
struct node_rx_ftr *ftr = &node_rx->hdr.rx_ftr;
55265527
int8_t tx_pwr = BT_HCI_LE_ADV_TX_POWER_NO_PREF;
55275528
struct pdu_adv *adv = (void *)pdu_data;
5529+
struct pdu_adv_aux_ptr *aux_ptr = NULL;
55285530
uint8_t cte_type = BT_HCI_LE_NO_CTE;
5529-
struct node_rx_pdu *node_rx_curr;
5530-
struct node_rx_pdu *node_rx_next;
5531-
uint8_t total_data_len = 0U;
5531+
struct pdu_adv_com_ext_adv *p;
5532+
struct pdu_adv_ext_hdr *h;
55325533
uint8_t data_status = 0U;
5534+
struct net_buf *evt_buf;
55335535
uint8_t data_len = 0U;
55345536
uint8_t *data = NULL;
55355537
uint8_t data_max_len;
5538+
uint8_t hdr_buf_len;
5539+
uint8_t hdr_len;
5540+
uint8_t *ptr;
55365541
int8_t rssi;
55375542

55385543
if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
55395544
!(le_event_mask & BT_EVT_MASK_LE_PER_ADVERTISING_REPORT)) {
5540-
node_rx_extra_list_release(node_rx->hdr.rx_ftr.extra);
55415545
return;
55425546
}
55435547

5544-
node_rx_curr = node_rx;
5545-
node_rx_next = node_rx_curr->hdr.rx_ftr.extra;
5546-
do {
5547-
struct pdu_adv_com_ext_adv *p;
5548-
uint8_t data_len_curr = 0U;
5549-
uint8_t *data_curr = NULL;
5550-
uint8_t sec_phy_curr = 0U;
5551-
struct pdu_adv_ext_hdr *h;
5552-
uint8_t hdr_buf_len;
5553-
uint8_t hdr_len;
5554-
uint8_t *ptr;
5555-
5556-
/* The Link Layer currently returns RSSI as an absolute value */
5557-
rssi = -(node_rx_curr->hdr.rx_ftr.rssi);
5558-
5559-
BT_DBG("len = %u, rssi = %d", adv->len, rssi);
5548+
/* The Link Layer currently returns RSSI as an absolute value */
5549+
rssi = -(node_rx->hdr.rx_ftr.rssi);
55605550

5561-
p = (void *)&adv->adv_ext_ind;
5562-
h = (void *)p->ext_hdr_adv_data;
5563-
ptr = (void *)h;
5551+
BT_DBG("len = %u, rssi = %d", adv->len, rssi);
55645552

5565-
BT_DBG(" Ext. adv mode= 0x%x, hdr len= %u", p->adv_mode,
5566-
p->ext_hdr_len);
5553+
p = (void *)&adv->adv_ext_ind;
5554+
h = (void *)p->ext_hdr_adv_data;
5555+
ptr = (void *)h;
55675556

5568-
if (!p->ext_hdr_len) {
5569-
hdr_len = PDU_AC_EXT_HEADER_SIZE_MIN;
5557+
BT_DBG(" Per. adv mode= 0x%x, hdr len= %u", p->adv_mode,
5558+
p->ext_hdr_len);
55705559

5571-
goto no_ext_hdr;
5572-
}
5560+
if (!p->ext_hdr_len) {
5561+
hdr_len = PDU_AC_EXT_HEADER_SIZE_MIN;
55735562

5574-
ptr = h->data;
5563+
goto no_ext_hdr;
5564+
}
55755565

5576-
if (h->adv_addr) {
5577-
ptr += BDADDR_SIZE;
5578-
}
5566+
ptr = h->data;
55795567

5580-
if (h->tgt_addr) {
5581-
ptr += BDADDR_SIZE;
5582-
}
5568+
if (h->adv_addr) {
5569+
ptr += BDADDR_SIZE;
5570+
}
55835571

5584-
if (h->cte_info) {
5585-
struct pdu_cte_info *cte_info;
5572+
if (h->tgt_addr) {
5573+
ptr += BDADDR_SIZE;
5574+
}
55865575

5587-
cte_info = (void *)ptr;
5588-
cte_type = cte_info->type;
5589-
ptr++;
5576+
if (h->cte_info) {
5577+
struct pdu_cte_info *cte_info;
55905578

5591-
BT_DBG(" CTE type= %d", cte_type);
5592-
}
5579+
cte_info = (void *)ptr;
5580+
cte_type = cte_info->type;
5581+
ptr++;
55935582

5594-
if (h->adi) {
5595-
ptr += sizeof(struct pdu_adv_adi);
5596-
}
5583+
BT_DBG(" CTE type= %d", cte_type);
5584+
}
55975585

5598-
/* AuxPtr */
5599-
if (h->aux_ptr) {
5600-
struct pdu_adv_aux_ptr *aux_ptr;
5601-
uint8_t aux_phy;
5586+
if (h->adi) {
5587+
ptr += sizeof(struct pdu_adv_adi);
5588+
}
56025589

5603-
aux_ptr = (void *)ptr;
5604-
if (aux_ptr->phy > EXT_ADV_AUX_PHY_LE_CODED) {
5605-
struct node_rx_ftr *ftr;
5590+
/* AuxPtr */
5591+
if (h->aux_ptr) {
5592+
uint8_t aux_phy;
56065593

5607-
ftr = &node_rx->hdr.rx_ftr;
5608-
node_rx_extra_list_release(ftr->extra);
5609-
return;
5610-
}
5594+
aux_ptr = (void *)ptr;
5595+
if (aux_ptr->phy > EXT_ADV_AUX_PHY_LE_CODED) {
5596+
struct node_rx_ftr *ftr;
56115597

5612-
ptr += sizeof(*aux_ptr);
5598+
ftr = &node_rx->hdr.rx_ftr;
5599+
node_rx_extra_list_release(ftr->extra);
5600+
return;
5601+
}
56135602

5614-
sec_phy_curr = aux_ptr->phy + 1;
5603+
ptr += sizeof(*aux_ptr);
56155604

5616-
aux_phy = BIT(aux_ptr->phy);
5605+
aux_phy = BIT(aux_ptr->phy);
56175606

5618-
BT_DBG(" AuxPtr chan_idx = %u, ca = %u, offs_units "
5619-
"= %u offs = 0x%x, phy = 0x%x",
5620-
aux_ptr->chan_idx, aux_ptr->ca,
5621-
aux_ptr->offs_units, aux_ptr->offs, aux_phy);
5622-
}
5607+
BT_DBG(" AuxPtr chan_idx = %u, ca = %u, offs_units "
5608+
"= %u offs = 0x%x, phy = 0x%x",
5609+
aux_ptr->chan_idx, aux_ptr->ca,
5610+
aux_ptr->offs_units, aux_ptr->offs, aux_phy);
5611+
}
56235612

5624-
/* No SyncInfo */
5625-
if (h->sync_info) {
5626-
ptr += sizeof(struct pdu_adv_sync_info);
5627-
}
5613+
/* No SyncInfo */
5614+
if (h->sync_info) {
5615+
ptr += sizeof(struct pdu_adv_sync_info);
5616+
}
56285617

5629-
/* Tx Power */
5630-
if (h->tx_pwr) {
5631-
tx_pwr = *(int8_t *)ptr;
5632-
ptr++;
5618+
/* Tx Power */
5619+
if (h->tx_pwr) {
5620+
tx_pwr = *(int8_t *)ptr;
5621+
ptr++;
56335622

5634-
BT_DBG(" Tx pwr= %d dB", tx_pwr);
5635-
}
5623+
BT_DBG(" Tx pwr= %d dB", tx_pwr);
5624+
}
56365625

5637-
hdr_len = ptr - (uint8_t *)p;
5626+
hdr_len = ptr - (uint8_t *)p;
56385627
if (hdr_len <= (PDU_AC_EXT_HEADER_SIZE_MIN +
56395628
sizeof(struct pdu_adv_ext_hdr))) {
56405629
hdr_len = PDU_AC_EXT_HEADER_SIZE_MIN;
56415630
ptr = (uint8_t *)h;
56425631
}
56435632

5644-
hdr_buf_len = PDU_AC_EXT_HEADER_SIZE_MIN + p->ext_hdr_len;
5645-
if (hdr_len > hdr_buf_len) {
5646-
BT_WARN(" Header length %u/%u, INVALID.", hdr_len,
5647-
p->ext_hdr_len);
5648-
} else {
5649-
uint8_t acad_len = hdr_buf_len - hdr_len;
5633+
hdr_buf_len = PDU_AC_EXT_HEADER_SIZE_MIN + p->ext_hdr_len;
5634+
if (hdr_len > hdr_buf_len) {
5635+
BT_WARN(" Header length %u/%u, INVALID.", hdr_len,
5636+
p->ext_hdr_len);
5637+
} else {
5638+
uint8_t acad_len = hdr_buf_len - hdr_len;
56505639

5651-
if (acad_len) {
5652-
ptr += acad_len;
5653-
hdr_len += acad_len;
5640+
if (acad_len) {
5641+
ptr += acad_len;
5642+
hdr_len += acad_len;
56545643

5655-
BT_DBG("ACAD: <todo>");
5656-
}
5644+
BT_DBG("ACAD: <todo>");
56575645
}
5646+
}
56585647

56595648
no_ext_hdr:
5660-
if (hdr_len < adv->len) {
5661-
data_len_curr = adv->len - hdr_len;
5662-
data_curr = ptr;
5663-
5664-
BT_DBG(" AD Data (%u): <todo>", data_len);
5665-
}
5666-
5667-
if (node_rx_curr == node_rx) {
5668-
data_len = data_len_curr;
5669-
total_data_len = data_len;
5670-
data = data_curr;
5671-
} else {
5672-
/* TODO: Validate current value with previous ??
5673-
*/
5674-
5675-
if (!data) {
5676-
data_len = data_len_curr;
5677-
total_data_len = data_len;
5678-
data = data_curr;
5679-
} else {
5680-
total_data_len += data_len_curr;
5681-
5682-
/* TODO: construct new HCI event for this
5683-
* fragment.
5684-
*/
5685-
}
5686-
}
5687-
5688-
if (!node_rx_next) {
5689-
bool has_aux_ptr = !!sec_phy_curr;
5690-
5691-
if (has_aux_ptr) {
5692-
data_status =
5693-
BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_INCOMPLETE;
5694-
}
5649+
if (hdr_len < adv->len) {
5650+
data_len = adv->len - hdr_len;
5651+
data = ptr;
56955652

5696-
break;
5697-
}
5653+
BT_DBG(" AD Data (%u): <todo>", data_len);
5654+
}
56985655

5699-
node_rx_curr = node_rx_next;
5700-
node_rx_next = node_rx_curr->hdr.rx_ftr.extra;
5701-
adv = (void *)node_rx_curr->pdu;
5702-
} while (1);
5656+
adv = (void *)node_rx->pdu;
57035657

5704-
/* FIXME: move most of below into above loop to dispatch fragments of
5705-
* data in HCI event.
5706-
*/
57075658
data_max_len = ADV_REPORT_EVT_MAX_LEN -
57085659
sizeof(struct bt_hci_evt_le_meta_event) -
57095660
sizeof(*sep);
57105661

5711-
/* If data complete */
5712-
if (!data_status) {
5713-
/* Only copy data that fit the event buffer size,
5714-
* mark it as incomplete
5715-
*/
5716-
if (data_len > data_max_len) {
5717-
data_len = data_max_len;
5718-
data_status =
5719-
BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_PARTIAL;
5720-
}
5662+
evt_buf = buf;
57215663

5722-
/* else, data incomplete */
5723-
} else {
5724-
/* Data incomplete and no more to come */
5725-
if ((tx_pwr == BT_HCI_LE_ADV_TX_POWER_NO_PREF) && !data) {
5726-
/* No Tx Power value and no valid AD data parsed in this
5727-
* chain of PDUs, skip HCI event generation.
5664+
do {
5665+
uint8_t data_len_frag;
5666+
5667+
data_len_frag = MIN(data_len, data_max_len);
5668+
5669+
/* Start constructing periodic advertising report */
5670+
sep = meta_evt(evt_buf,
5671+
BT_HCI_EVT_LE_PER_ADVERTISING_REPORT,
5672+
sizeof(*sep) + data_len_frag);
5673+
5674+
memcpy(&sep->data[0], data, data_len_frag);
5675+
data += data_len_frag;
5676+
data_len -= data_len_frag;
5677+
5678+
if (data_len > 0) {
5679+
/* Some data left in PDU, mark as partial data. */
5680+
data_status = BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_PARTIAL;
5681+
} else if (!aux_ptr) {
5682+
/* No data left, no AuxPtr, mark as complete data. */
5683+
data_status = BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_COMPLETE;
5684+
} else if (ftr->aux_w4next) {
5685+
/* No data left, but have AuxPtr and scheduled aux scan,
5686+
* mark as partial data.
57285687
*/
5729-
node_rx_extra_list_release(node_rx->hdr.rx_ftr.extra);
5730-
return;
5731-
}
5732-
5733-
/* Only copy data that fit the event buffer size */
5734-
if (data_len > data_max_len) {
5735-
data_len = data_max_len;
5688+
data_status = BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_PARTIAL;
5689+
} else {
5690+
/* No data left, have AuxPtr but not aux scan scheduled,
5691+
* mark as incomplete data.
5692+
*/
5693+
data_status = BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_INCOMPLETE;
57365694
}
5737-
}
57385695

5739-
/* Start constructing the event */
5740-
sep = meta_evt(buf, BT_HCI_EVT_LE_PER_ADVERTISING_REPORT,
5741-
sizeof(*sep) + data_len);
5696+
sep->handle = sys_cpu_to_le16(node_rx->hdr.handle);
5697+
sep->tx_power = tx_pwr;
5698+
sep->rssi = rssi;
5699+
sep->cte_type = cte_type;
5700+
sep->data_status = data_status;
5701+
sep->length = data_len_frag;
57425702

5743-
sep->handle = sys_cpu_to_le16(node_rx->hdr.handle);
5744-
sep->tx_power = tx_pwr;
5745-
sep->rssi = rssi;
5746-
sep->cte_type = cte_type;
5747-
sep->data_status = data_status;
5748-
sep->length = data_len;
5749-
memcpy(&sep->data[0], data, data_len);
5703+
if (data_len > 0) {
5704+
evt_buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER);
5705+
net_buf_frag_add(buf, evt_buf);
57505706

5751-
node_rx_extra_list_release(node_rx->hdr.rx_ftr.extra);
5707+
tx_pwr = BT_HCI_LE_ADV_TX_POWER_NO_PREF;
5708+
}
5709+
} while (data_len > 0);
57525710
}
57535711

57545712
static void le_per_adv_sync_lost(struct pdu_data *pdu_data,

subsys/bluetooth/controller/ll_sw/lll.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,13 +276,15 @@ struct node_rx_ftr {
276276
*/
277277
void *aux_ptr;
278278
uint8_t aux_phy;
279-
uint8_t aux_sched;
280279
};
281280
uint32_t ticks_anchor;
282281
uint32_t radio_end_us;
283282
uint8_t rssi;
284283
#if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_OBSERVER)
285284
uint8_t aux_sched_from_lll:1;
285+
uint8_t aux_lll_sched:1;
286+
uint8_t aux_w4next:1;
287+
286288
uint8_t phy_flags:1;
287289
uint8_t scan_req:1;
288290
uint8_t scan_rsp:1;

subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1454,11 +1454,11 @@ static int isr_rx_scan_report(struct lll_scan *lll, uint8_t rssi_ready,
14541454
radio_rx_chain_delay_get(lll->phy,
14551455
phy_flags_rx);
14561456
ftr->phy_flags = phy_flags_rx;
1457-
ftr->aux_sched =
1457+
ftr->aux_lll_sched =
14581458
lll_scan_aux_setup(lll, NULL, pdu_adv_rx,
14591459
lll->phy,
14601460
phy_flags_rx);
1461-
if (ftr->aux_sched) {
1461+
if (ftr->aux_lll_sched) {
14621462
err = -EBUSY;
14631463
}
14641464
}

0 commit comments

Comments
 (0)