Bluetooth: controller: Integrate extended adv report into HCI
Integrate the generated extended adv report PDU list into HCI layer to generate the HCI LE Extended Advertising Report event. Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
parent
0c058badf2
commit
8eebc2e926
1 changed files with 225 additions and 33 deletions
|
@ -3172,40 +3172,74 @@ static void le_ext_adv_legacy_report(struct pdu_data *pdu_data,
|
||||||
memcpy(&adv_info->data[0], &adv->adv_ind.data[0], data_len);
|
memcpy(&adv_info->data[0], &adv->adv_ind.data[0], data_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void le_adv_ext_report(struct pdu_data *pdu_data,
|
static void le_ext_adv_report(struct pdu_data *pdu_data,
|
||||||
struct node_rx_pdu *node_rx,
|
struct node_rx_pdu *node_rx,
|
||||||
struct net_buf *buf, uint8_t phy)
|
struct net_buf *buf, uint8_t phy)
|
||||||
{
|
{
|
||||||
|
struct bt_hci_evt_le_ext_advertising_info *adv_info;
|
||||||
|
struct bt_hci_evt_le_ext_advertising_report *sep;
|
||||||
struct pdu_adv *adv = (void *)pdu_data;
|
struct pdu_adv *adv = (void *)pdu_data;
|
||||||
|
struct node_rx_pdu *node_rx_curr;
|
||||||
|
struct node_rx_pdu *node_rx_next;
|
||||||
|
struct ext_adv_adi *adi = NULL;
|
||||||
|
uint8_t direct_addr_type = 0U;
|
||||||
|
uint8_t *direct_addr = NULL;
|
||||||
|
uint8_t total_data_len = 0U;
|
||||||
|
uint8_t adv_addr_type = 0U;
|
||||||
|
uint8_t *adv_addr = NULL;
|
||||||
|
uint8_t data_status = 0U;
|
||||||
|
uint8_t data_len = 0U;
|
||||||
|
uint8_t evt_type = 0U;
|
||||||
|
int8_t tx_pwr = 0x7f;
|
||||||
|
uint8_t *data = NULL;
|
||||||
|
uint8_t sec_phy = 0U;
|
||||||
|
int8_t rssi = 0x7f;
|
||||||
|
uint8_t info_len;
|
||||||
|
|
||||||
if ((adv->type == PDU_ADV_TYPE_EXT_IND) && adv->len) {
|
#if defined(CONFIG_BT_CTLR_PRIVACY)
|
||||||
|
uint8_t rl_idx;
|
||||||
|
#endif /* CONFIG_BT_CTLR_PRIVACY */
|
||||||
|
|
||||||
|
if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
|
||||||
|
!(le_event_mask & BT_EVT_MASK_LE_EXT_ADVERTISING_REPORT)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node_rx_curr = node_rx;
|
||||||
|
node_rx_next = node_rx_curr->hdr.rx_ftr.extra;
|
||||||
|
do {
|
||||||
|
struct ext_adv_adi *adi_curr = NULL;
|
||||||
|
uint8_t direct_addr_type_curr = 0U;
|
||||||
struct pdu_adv_com_ext_adv *p;
|
struct pdu_adv_com_ext_adv *p;
|
||||||
|
uint8_t *direct_addr_curr = NULL;
|
||||||
|
uint8_t adv_addr_type_curr = 0U;
|
||||||
|
uint8_t *adv_addr_curr = NULL;
|
||||||
|
uint8_t data_len_curr = 0U;
|
||||||
|
uint8_t *data_curr = NULL;
|
||||||
struct ext_adv_hdr *h;
|
struct ext_adv_hdr *h;
|
||||||
|
uint8_t sec_phy_curr = 0U;
|
||||||
|
uint8_t evt_type_curr;
|
||||||
uint8_t *ptr;
|
uint8_t *ptr;
|
||||||
int8_t rssi;
|
|
||||||
|
|
||||||
#if !defined(CONFIG_BT_LL_SW_SPLIT)
|
|
||||||
uint8_t *extra;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(CONFIG_BT_LL_SW_SPLIT)
|
|
||||||
/* The Link Layer currently returns RSSI as an absolute value */
|
/* The Link Layer currently returns RSSI as an absolute value */
|
||||||
rssi = -(node_rx->hdr.rx_ftr.rssi);
|
rssi = -(node_rx_curr->hdr.rx_ftr.rssi);
|
||||||
#else
|
|
||||||
extra = &adv->payload[adv->len];
|
|
||||||
rssi = -(*extra);
|
|
||||||
#endif /* CONFIG_BT_LL_SW_SPLIT */
|
|
||||||
|
|
||||||
BT_INFO("phy= 0x%x, type= 0x%x, len= %u, tat= %u, rat= %u,"
|
#if defined(CONFIG_BT_CTLR_PRIVACY)
|
||||||
" rssi=%d dB", phy, adv->type, adv->len, adv->tx_addr,
|
rl_idx = node_rx_curr->hdr.rx_ftr.rl_idx;
|
||||||
adv->rx_addr, rssi);
|
#endif /* CONFIG_BT_CTLR_PRIVACY */
|
||||||
|
|
||||||
|
BT_DBG("phy= 0x%x, type= 0x%x, len= %u, tat= %u, rat= %u,"
|
||||||
|
" rssi=%d dB", phy, adv->type, adv->len, adv->tx_addr,
|
||||||
|
adv->rx_addr, rssi);
|
||||||
|
|
||||||
p = (void *)&adv->adv_ext_ind;
|
p = (void *)&adv->adv_ext_ind;
|
||||||
h = (void *)p->ext_hdr_adi_adv_data;
|
h = (void *)p->ext_hdr_adi_adv_data;
|
||||||
ptr = (uint8_t *)h + sizeof(*h);
|
ptr = (uint8_t *)h + sizeof(*h);
|
||||||
|
|
||||||
BT_INFO(" Ext. adv mode= 0x%x, hdr len= %u", p->adv_mode,
|
BT_DBG(" Ext. adv mode= 0x%x, hdr len= %u", p->adv_mode,
|
||||||
p->ext_hdr_len);
|
p->ext_hdr_len);
|
||||||
|
|
||||||
|
evt_type_curr = p->adv_mode;
|
||||||
|
|
||||||
if (!p->ext_hdr_len) {
|
if (!p->ext_hdr_len) {
|
||||||
goto no_ext_hdr;
|
goto no_ext_hdr;
|
||||||
|
@ -3214,30 +3248,35 @@ static void le_adv_ext_report(struct pdu_data *pdu_data,
|
||||||
if (h->adv_addr) {
|
if (h->adv_addr) {
|
||||||
bt_addr_le_t addr;
|
bt_addr_le_t addr;
|
||||||
|
|
||||||
|
adv_addr_type_curr = adv->tx_addr;
|
||||||
|
adv_addr_curr = ptr;
|
||||||
|
|
||||||
addr.type = adv->tx_addr;
|
addr.type = adv->tx_addr;
|
||||||
memcpy(&addr.a.val[0], ptr, sizeof(bt_addr_t));
|
memcpy(&addr.a.val[0], ptr, sizeof(bt_addr_t));
|
||||||
ptr += BDADDR_SIZE;
|
ptr += BDADDR_SIZE;
|
||||||
|
|
||||||
BT_INFO(" AdvA: %s", bt_addr_le_str(&addr));
|
BT_DBG(" AdvA: %s", bt_addr_le_str(&addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h->tgt_addr) {
|
if (h->tgt_addr) {
|
||||||
bt_addr_le_t addr;
|
bt_addr_le_t addr;
|
||||||
|
|
||||||
|
direct_addr_type_curr = adv->rx_addr;
|
||||||
|
direct_addr_curr = ptr;
|
||||||
|
|
||||||
addr.type = adv->rx_addr;
|
addr.type = adv->rx_addr;
|
||||||
memcpy(&addr.a.val[0], ptr, sizeof(bt_addr_t));
|
memcpy(&addr.a.val[0], ptr, sizeof(bt_addr_t));
|
||||||
ptr += BDADDR_SIZE;
|
ptr += BDADDR_SIZE;
|
||||||
|
|
||||||
BT_INFO(" TgtA: %s", bt_addr_le_str(&addr));
|
BT_DBG(" TgtA: %s", bt_addr_le_str(&addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h->adi) {
|
if (h->adi) {
|
||||||
struct ext_adv_adi *adi;
|
adi_curr = (void *)ptr;
|
||||||
|
|
||||||
adi = (void *)ptr;
|
|
||||||
ptr += sizeof(*adi);
|
ptr += sizeof(*adi);
|
||||||
|
|
||||||
BT_INFO(" AdvDataInfo DID = 0x%x, SID = 0x%x",
|
BT_DBG(" AdvDataInfo DID = 0x%x, SID = 0x%x",
|
||||||
adi->did, adi->sid);
|
adi->did, adi->sid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3248,20 +3287,20 @@ static void le_adv_ext_report(struct pdu_data *pdu_data,
|
||||||
aux = (void *)ptr;
|
aux = (void *)ptr;
|
||||||
ptr += sizeof(*aux);
|
ptr += sizeof(*aux);
|
||||||
|
|
||||||
|
sec_phy_curr = aux->phy + 1;
|
||||||
|
|
||||||
aux_phy = BIT(aux->phy);
|
aux_phy = BIT(aux->phy);
|
||||||
|
|
||||||
BT_INFO(" AuxPtr chan_idx = %u, ca = %u, offs_units "
|
BT_DBG(" AuxPtr chan_idx = %u, ca = %u, offs_units "
|
||||||
"= %u offs = 0x%x, phy = 0x%x", aux->chan_idx,
|
"= %u offs = 0x%x, phy = 0x%x", aux->chan_idx,
|
||||||
aux->ca, aux->offs_units, aux->offs, aux_phy);
|
aux->ca, aux->offs_units, aux->offs, aux_phy);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h->tx_pwr) {
|
if (h->tx_pwr) {
|
||||||
int8_t tx_pwr;
|
|
||||||
|
|
||||||
tx_pwr = *(int8_t *)ptr;
|
tx_pwr = *(int8_t *)ptr;
|
||||||
ptr++;
|
ptr++;
|
||||||
|
|
||||||
BT_INFO(" Tx pwr= %d dB", tx_pwr);
|
BT_DBG(" Tx pwr= %d dB", tx_pwr);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t len = ptr - (uint8_t *)p;
|
uint8_t len = ptr - (uint8_t *)p;
|
||||||
|
@ -3277,21 +3316,174 @@ static void le_adv_ext_report(struct pdu_data *pdu_data,
|
||||||
ptr += acad_len;
|
ptr += acad_len;
|
||||||
len += acad_len;
|
len += acad_len;
|
||||||
|
|
||||||
BT_INFO("ACAD: <todo>");
|
BT_DBG("ACAD: <todo>");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len < adv->len) {
|
if (len < adv->len) {
|
||||||
uint8_t ad_len = adv->len - len;
|
data_len_curr = adv->len - len;
|
||||||
|
data_curr = ptr;
|
||||||
|
|
||||||
BT_INFO(" AD Data (%u): <todo>", ad_len);
|
BT_DBG(" AD Data (%u): <todo>", data_len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
no_ext_hdr:
|
||||||
|
if (node_rx_curr == node_rx) {
|
||||||
|
evt_type = evt_type_curr;
|
||||||
|
adv_addr_type = adv_addr_type_curr;
|
||||||
|
adv_addr = adv_addr_curr;
|
||||||
|
direct_addr_type = direct_addr_type_curr;
|
||||||
|
direct_addr = direct_addr_curr;
|
||||||
|
adi = adi_curr;
|
||||||
|
sec_phy = sec_phy_curr;
|
||||||
|
data_len = data_len_curr;
|
||||||
|
total_data_len = data_len;
|
||||||
|
data = data_curr;
|
||||||
|
} else {
|
||||||
|
/* TODO: Validate current value with previous, also
|
||||||
|
* detect the scan response in the list of node_rx.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!adv_addr) {
|
||||||
|
adv_addr_type = adv_addr_type_curr;
|
||||||
|
adv_addr = adv_addr_curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!direct_addr) {
|
||||||
|
direct_addr_type = direct_addr_type_curr;
|
||||||
|
direct_addr = direct_addr_curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
data_len = data_len_curr;
|
||||||
|
total_data_len = data_len;
|
||||||
|
data = data_curr;
|
||||||
|
} else {
|
||||||
|
total_data_len += data_len_curr;
|
||||||
|
|
||||||
|
/* TODO: construct new HCI event for this
|
||||||
|
* fragment.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!node_rx_next) {
|
||||||
|
if (sec_phy_curr) {
|
||||||
|
data_status = BIT(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
node_rx_curr = node_rx_next;
|
||||||
|
node_rx_next = node_rx_curr->hdr.rx_ftr.extra;
|
||||||
|
adv = (void *)node_rx_curr->pdu;
|
||||||
|
} while (1);
|
||||||
|
|
||||||
|
/* FIXME: move most of below into above loop to dispatch fragments of
|
||||||
|
* data in HCI event.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* If data complete */
|
||||||
|
if (!data_status) {
|
||||||
|
uint8_t data_max_len;
|
||||||
|
|
||||||
|
data_max_len = CONFIG_BT_DISCARDABLE_BUF_SIZE -
|
||||||
|
BT_HCI_ACL_HDR_SIZE - sizeof(*sep) -
|
||||||
|
sizeof(*adv_info);
|
||||||
|
|
||||||
|
/* if data cannot fit the event, mark it as incomplete */
|
||||||
|
if (data_len > data_max_len) {
|
||||||
|
data_len = data_max_len;
|
||||||
|
data_status = BIT(0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Data incomplete and no more to come */
|
||||||
|
if (!(adv_addr || (adi && ((tx_pwr != 0x7f) || data)))) {
|
||||||
|
goto le_ext_adv_report_invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start constructing the event */
|
||||||
|
info_len = sizeof(struct bt_hci_evt_le_ext_advertising_info) +
|
||||||
|
data_len;
|
||||||
|
sep = meta_evt(buf, BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT,
|
||||||
|
sizeof(*sep) + info_len);
|
||||||
|
|
||||||
|
sep->num_reports = 1U;
|
||||||
|
adv_info = (void *)(((uint8_t *)sep) + sizeof(*sep));
|
||||||
|
|
||||||
|
/* Set directed advertising bit */
|
||||||
|
if ((evt_type == BT_HCI_LE_ADV_EVT_TYPE_CONN) && direct_addr) {
|
||||||
|
evt_type |= BIT(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Set scan response bit */
|
||||||
|
|
||||||
|
/* set data status bits */
|
||||||
|
evt_type |= (data_status << 5);
|
||||||
|
|
||||||
|
adv_info->evt_type = evt_type;
|
||||||
|
|
||||||
|
if (0) {
|
||||||
|
#if defined(CONFIG_BT_CTLR_PRIVACY)
|
||||||
|
} else if (rl_idx < ll_rl_size_get()) {
|
||||||
|
/* Store identity address */
|
||||||
|
ll_rl_id_addr_get(rl_idx, &adv_info->addr.type,
|
||||||
|
&adv_info->addr.a.val[0]);
|
||||||
|
/* Mark it as identity address from RPA (0x02, 0x03) */
|
||||||
|
adv_info->addr.type += 2U;
|
||||||
|
#endif /* CONFIG_BT_CTLR_PRIVACY */
|
||||||
|
} else if (adv_addr) {
|
||||||
|
adv_info->addr.type = adv_addr_type;
|
||||||
|
memcpy(&adv_info->addr.a.val[0], adv_addr, sizeof(bt_addr_t));
|
||||||
|
} else {
|
||||||
|
adv_info->addr.type = 0U;
|
||||||
|
memset(&adv_info->addr.a.val[0], 0, sizeof(bt_addr_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
adv_info->prim_phy = find_lsb_set(phy);
|
||||||
|
adv_info->sec_phy = sec_phy;
|
||||||
|
adv_info->sid = (adi) ? adi->sid : 0U;
|
||||||
|
adv_info->tx_power = tx_pwr;
|
||||||
|
adv_info->rssi = rssi;
|
||||||
|
adv_info->interval = 0U;
|
||||||
|
|
||||||
|
if (evt_type & BT_HCI_LE_ADV_EVT_TYPE_DIRECT) {
|
||||||
|
adv_info->direct_addr.type = direct_addr_type;
|
||||||
|
memcpy(&adv_info->direct_addr.a.val[0], direct_addr,
|
||||||
|
sizeof(bt_addr_t));
|
||||||
|
} else {
|
||||||
|
adv_info->direct_addr.type = 0U;
|
||||||
|
memset(&adv_info->direct_addr.a.val[0], 0, sizeof(bt_addr_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
adv_info->length = data_len;
|
||||||
|
memcpy(&adv_info->data[0], data, data_len);
|
||||||
|
|
||||||
|
le_ext_adv_report_invalid:
|
||||||
|
/* Free the node_rx list */
|
||||||
|
node_rx_next = node_rx->hdr.rx_ftr.extra;
|
||||||
|
while (node_rx_next) {
|
||||||
|
node_rx_curr = node_rx_next;
|
||||||
|
node_rx_next = node_rx_curr->hdr.rx_ftr.extra;
|
||||||
|
|
||||||
|
node_rx_curr->hdr.next = NULL;
|
||||||
|
ll_rx_mem_release((void **)&node_rx_curr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void le_adv_ext_report(struct pdu_data *pdu_data,
|
||||||
|
struct node_rx_pdu *node_rx,
|
||||||
|
struct net_buf *buf, uint8_t phy)
|
||||||
|
{
|
||||||
|
struct pdu_adv *adv = (void *)pdu_data;
|
||||||
|
|
||||||
|
if ((adv->type == PDU_ADV_TYPE_EXT_IND) && adv->len) {
|
||||||
|
le_ext_adv_report(pdu_data, node_rx, buf, phy);
|
||||||
} else {
|
} else {
|
||||||
le_ext_adv_legacy_report(pdu_data, node_rx, buf);
|
le_ext_adv_legacy_report(pdu_data, node_rx, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
no_ext_hdr:
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void le_adv_ext_1M_report(struct pdu_data *pdu_data,
|
static void le_adv_ext_1M_report(struct pdu_data *pdu_data,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue