This is an automated email from the ASF dual-hosted git repository. andk pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git
commit 06bc61ee35103c9bccf4e1515f47887de691fc63 Author: Michal Gorecki <michal.gore...@codecoup.pl> AuthorDate: Thu May 25 15:39:20 2023 +0200 nimble/ll: Add HCI events for BIGInfo reports --- nimble/controller/include/controller/ble_ll.h | 1 + nimble/controller/src/ble_ll_sync.c | 92 ++++++++++++++++++++++++++- nimble/controller/syscfg.yml | 6 ++ 3 files changed, 97 insertions(+), 2 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll.h b/nimble/controller/include/controller/ble_ll.h index 35b562a9..c4e70e6e 100644 --- a/nimble/controller/include/controller/ble_ll.h +++ b/nimble/controller/include/controller/ble_ll.h @@ -475,6 +475,7 @@ struct ble_dev_addr /* ACAD data types */ #define BLE_LL_ACAD_CHANNEL_MAP_UPDATE_IND 0x28 +#define BLE_LL_ACAD_BIGINFO 0x2C struct ble_ll_acad_channel_map_update_ind { uint8_t map[5]; diff --git a/nimble/controller/src/ble_ll_sync.c b/nimble/controller/src/ble_ll_sync.c index f06f87c1..f10a5993 100644 --- a/nimble/controller/src/ble_ll_sync.c +++ b/nimble/controller/src/ble_ll_sync.c @@ -66,6 +66,9 @@ #define BLE_LL_SYNC_ITVL_USECS 1250 +#define BLE_LL_SYNC_BIGINFO_LEN 33 +#define BLE_LL_SYNC_BIGINFO_LEN_ENC 57 + struct ble_ll_sync_sm { uint16_t flags; @@ -661,6 +664,70 @@ ble_ll_sync_send_truncated_per_adv_rpt(struct ble_ll_sync_sm *sm, uint8_t *evbuf ble_ll_hci_event_send(hci_ev); } +#if MYNEWT_VAL(BLE_LL_PERIODIC_ADV_SYNC_BIGINFO_REPORTS) +static void +ble_ll_sync_parse_biginfo_to_ev(struct ble_hci_ev_le_subev_biginfo_adv_report *ev, + const uint8_t *biginfo, uint8_t biginfo_len) +{ + uint32_t fields_buf; + + fields_buf = get_le32(&biginfo[0]); + ev->iso_interval = (fields_buf >> 15) & 0x0FFF; + ev->bis_cnt = (fields_buf >> 27) & 0x1F; + + fields_buf = get_le32(&biginfo[4]); + ev->nse = fields_buf & 0x1F; + ev->bn = (fields_buf >> 5) & 0x07; + ev->pto = (fields_buf >> 28) & 0x0F; + + fields_buf = get_le32(&biginfo[8]); + ev->irc = (fields_buf >> 20) & 0x0F; + ev->max_pdu = (fields_buf >> 24) & 0xFF; + + fields_buf = get_le32(&biginfo[17]); + ev->sdu_interval[0] = fields_buf & 0xFF; + ev->sdu_interval[1] = (fields_buf >> 8) & 0xFF; + ev->sdu_interval[2] = (fields_buf >> 16) & 0x0F; + ev->max_sdu = (fields_buf >> 20) & 0x0FFF; + + ev->phy = (biginfo[27] >> 5) & 0x07; + + ev->framing = (biginfo[32] >> 7) & 0x01; + + if (biginfo_len == BLE_LL_SYNC_BIGINFO_LEN_ENC) { + ev->encryption = 1; + } else { + ev->encryption = 0; + } +} + +static void +ble_ll_sync_send_biginfo_adv_rpt(struct ble_ll_sync_sm *sm, const uint8_t *biginfo, uint8_t biginfo_len) +{ + struct ble_hci_ev_le_subev_biginfo_adv_report *ev; + struct ble_hci_ev *hci_ev; + + if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_BIGINFO_ADV_REPORT)) { + return; + } + + hci_ev = ble_transport_alloc_evt(1); + if (!hci_ev) { + return; + } + + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + ev->subev_code = BLE_HCI_LE_SUBEV_BIGINFO_ADV_REPORT; + ev->sync_handle = htole16(ble_ll_sync_get_handle(sm)); + ble_ll_sync_parse_biginfo_to_ev(ev, biginfo, biginfo_len); + + ble_ll_hci_event_send(hci_ev); +} +#endif + static void ble_ll_sync_send_per_adv_rpt(struct ble_ll_sync_sm *sm, struct os_mbuf *rxpdu, int8_t rssi, int8_t tx_power, int datalen, @@ -963,7 +1030,8 @@ ble_ll_sync_check_failed(struct ble_ll_sync_sm *sm) static bool ble_ll_sync_check_acad(struct ble_ll_sync_sm *sm, - const uint8_t *acad, uint8_t acad_len) + const uint8_t *acad, uint8_t acad_len, + const uint8_t **biginfo, uint8_t *biginfo_len) { const struct ble_ll_acad_channel_map_update_ind *chmu; unsigned int ad_len; @@ -1009,6 +1077,18 @@ ble_ll_sync_check_acad(struct ble_ll_sync_sm *sm, sm->chan_map_new_instant = le16toh(chmu->instant); sm->flags |= BLE_LL_SYNC_SM_FLAG_NEW_CHANMAP; break; + +#if MYNEWT_VAL(BLE_LL_PERIODIC_ADV_SYNC_BIGINFO_REPORTS) + case BLE_LL_ACAD_BIGINFO: + if ((ad_len - 1 == BLE_LL_SYNC_BIGINFO_LEN) || (ad_len - 1 == BLE_LL_SYNC_BIGINFO_LEN_ENC)) { + *biginfo = &acad[2]; + *biginfo_len = ad_len - 1; + } else { + return false; + } + break; +#endif + default: break; } @@ -1034,6 +1114,8 @@ ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) uint8_t *aux = NULL; uint8_t *acad = NULL; uint8_t acad_len; + const uint8_t *biginfo = NULL; + uint8_t biginfo_len = 0; int datalen; bool reports_enabled; @@ -1099,7 +1181,7 @@ ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) } /* check ACAD, needs to be done before rxpdu is adjusted for ADV data */ - if (acad && !ble_ll_sync_check_acad(sm, acad, acad_len)) { + if (acad && !ble_ll_sync_check_acad(sm, acad, acad_len, &biginfo, &biginfo_len)) { /* we got bad packet (bad ACAD data), end event */ goto end_event; } @@ -1117,6 +1199,12 @@ ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) /* send reports from this PDU */ ble_ll_sync_send_per_adv_rpt(sm, rxpdu, hdr->rxinfo.rssi, tx_power, datalen, aux, aux_scheduled); + +#if MYNEWT_VAL(BLE_LL_PERIODIC_ADV_SYNC_BIGINFO_REPORTS) + if (biginfo) { + ble_ll_sync_send_biginfo_adv_rpt(sm, biginfo, biginfo_len); + } +#endif } /* if chain was scheduled we don't end event yet */ diff --git a/nimble/controller/syscfg.yml b/nimble/controller/syscfg.yml index 34039bb0..bff7b966 100644 --- a/nimble/controller/syscfg.yml +++ b/nimble/controller/syscfg.yml @@ -363,6 +363,12 @@ syscfg.defs: restrictions: - 'BLE_LL_CFG_FEAT_LL_ISO if 1' + BLE_LL_PERIODIC_ADV_SYNC_BIGINFO_REPORTS: + description: > + This option is used to enable/disable support for + handling BIGInfo data + value: 0 + BLE_LL_SCAN_AUX_SEGMENT_CNT: description: > Number of auxiliary advertising segments that can be scanned