Skip to content

Commit db9859b

Browse files
committed
nimble/ll: Fix BIGInfo report parsing
This fixes the missing BIGInfo size check as well as the PHY value passed to the HCI BIGInfo report, which was not corresponding to the one in the LL event. Additionally, this fix addresses the framing field. In accordance with the Core Specification, unsupported PHY reports are now discarded.
1 parent 8b6f3e8 commit db9859b

1 file changed

Lines changed: 59 additions & 12 deletions

File tree

nimble/controller/src/ble_ll_sync.c

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -673,11 +673,35 @@ ble_ll_sync_send_truncated_per_adv_rpt(struct ble_ll_sync_sm *sm, uint8_t *evbuf
673673
}
674674

675675
#if MYNEWT_VAL(BLE_LL_PERIODIC_ADV_SYNC_BIGINFO_REPORTS)
676+
static uint8_t
677+
ble_ll_sync_biginfo_phy_get(const uint8_t *biginfo)
678+
{
679+
uint8_t phy;
680+
681+
phy = (biginfo[27] >> 5) & 0x07;
682+
switch (phy) {
683+
case 0:
684+
return BLE_PHY_1M;
685+
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
686+
case 1:
687+
return BLE_PHY_2M;
688+
#endif
689+
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
690+
case 2:
691+
return BLE_PHY_CODED;
692+
#endif
693+
default:
694+
return 0x00;
695+
}
696+
}
697+
676698
static void
677699
ble_ll_sync_parse_biginfo_to_ev(struct ble_hci_ev_le_subev_biginfo_adv_report *ev,
678700
const uint8_t *biginfo, uint8_t biginfo_len)
679701
{
680702
uint32_t fields_buf;
703+
uint8_t framing_mode;
704+
uint8_t framed;
681705

682706
fields_buf = get_le32(&biginfo[0]);
683707
ev->iso_interval = (fields_buf >> 15) & 0x0FFF;
@@ -693,14 +717,20 @@ ble_ll_sync_parse_biginfo_to_ev(struct ble_hci_ev_le_subev_biginfo_adv_report *e
693717
ev->max_pdu = (fields_buf >> 24) & 0xFF;
694718

695719
fields_buf = get_le32(&biginfo[17]);
696-
ev->sdu_interval[0] = fields_buf & 0xFF;
697-
ev->sdu_interval[1] = (fields_buf >> 8) & 0xFF;
698-
ev->sdu_interval[2] = (fields_buf >> 16) & 0x0F;
720+
put_le24(ev->sdu_interval, fields_buf & 0x0FFFFF);
699721
ev->max_sdu = (fields_buf >> 20) & 0x0FFF;
700722

701-
ev->phy = (biginfo[27] >> 5) & 0x07;
723+
ev->phy = ble_ll_sync_biginfo_phy_get(biginfo);
702724

703-
ev->framing = (biginfo[32] >> 7) & 0x01;
725+
framed = (biginfo[32] >> 7) & 0x01;
726+
framing_mode = (biginfo[12] >> 7) & 0x01;
727+
if (framed && framing_mode) {
728+
ev->framing = BLE_HCI_ISO_FRAMING_FRAMED_UNSEGMENTED;
729+
} else if (framed) {
730+
ev->framing = BLE_HCI_ISO_FRAMING_FRAMED_SEGMENTABLE;
731+
} else {
732+
ev->framing = BLE_HCI_ISO_FRAMING_UNFRAMED;
733+
}
704734

705735
if (biginfo_len == BLE_LL_SYNC_BIGINFO_LEN_ENC) {
706736
ev->encryption = 1;
@@ -712,25 +742,42 @@ ble_ll_sync_parse_biginfo_to_ev(struct ble_hci_ev_le_subev_biginfo_adv_report *e
712742
static void
713743
ble_ll_sync_send_biginfo_adv_rpt(struct ble_ll_sync_sm *sm, const uint8_t *biginfo, uint8_t biginfo_len)
714744
{
715-
struct ble_hci_ev_le_subev_biginfo_adv_report *ev;
745+
struct ble_hci_ev_le_subev_biginfo_adv_report ev;
716746
struct ble_hci_ev *hci_ev;
717747

718748
if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_BIGINFO_ADV_REPORT)) {
719749
return;
720750
}
721751

752+
/* The BIGInfo length is 33 octets for an unencrypted BIG and 57 octets for an encrypted BIG. */
753+
if (biginfo_len != BLE_LL_SYNC_BIGINFO_LEN &&
754+
biginfo_len != BLE_LL_SYNC_BIGINFO_LEN_ENC) {
755+
return;
756+
}
757+
758+
memset(&ev, 0, sizeof(ev));
759+
ble_ll_sync_parse_biginfo_to_ev(&ev, biginfo, biginfo_len);
760+
761+
if (!ev.phy) {
762+
/* Core 6.0 | Vol 6, Part B, 4.4.5.2
763+
* If the PHY field of the BIGInfo specifies a PHY that the Link Layer does not support or is
764+
* reserved for future use, the Link Layer shall ignore the BIGInfo, shall not report the
765+
* BIGInfo to the Host, and shall not enter the Synchronization state for the BIG specified
766+
* in the BIGinfo.
767+
*/
768+
return;
769+
}
770+
722771
hci_ev = ble_transport_alloc_evt(1);
723772
if (!hci_ev) {
724773
return;
725774
}
726775

727776
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
728-
hci_ev->length = sizeof(*ev);
729-
ev = (void *) hci_ev->data;
730-
731-
ev->subev_code = BLE_HCI_LE_SUBEV_BIGINFO_ADV_REPORT;
732-
ev->sync_handle = htole16(ble_ll_sync_get_handle(sm));
733-
ble_ll_sync_parse_biginfo_to_ev(ev, biginfo, biginfo_len);
777+
hci_ev->length = sizeof(ev);
778+
ev.subev_code = BLE_HCI_LE_SUBEV_BIGINFO_ADV_REPORT;
779+
ev.sync_handle = htole16(ble_ll_sync_get_handle(sm));
780+
memcpy(hci_ev->data, &ev, sizeof(ev));
734781

735782
ble_ll_hci_event_send(hci_ev);
736783
}

0 commit comments

Comments
 (0)