Skip to content

Commit 56f90bc

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 56f90bc

1 file changed

Lines changed: 60 additions & 12 deletions

File tree

nimble/controller/src/ble_ll_sync.c

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -673,11 +673,36 @@ 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+
683+
switch (phy) {
684+
case 0:
685+
return BLE_PHY_1M;
686+
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
687+
case 1:
688+
return BLE_PHY_2M;
689+
#endif
690+
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
691+
case 2:
692+
return BLE_PHY_CODED;
693+
#endif
694+
default:
695+
return 0x00;
696+
}
697+
}
698+
676699
static void
677700
ble_ll_sync_parse_biginfo_to_ev(struct ble_hci_ev_le_subev_biginfo_adv_report *ev,
678701
const uint8_t *biginfo, uint8_t biginfo_len)
679702
{
680703
uint32_t fields_buf;
704+
uint8_t framing_mode;
705+
uint8_t framed;
681706

682707
fields_buf = get_le32(&biginfo[0]);
683708
ev->iso_interval = (fields_buf >> 15) & 0x0FFF;
@@ -693,14 +718,20 @@ ble_ll_sync_parse_biginfo_to_ev(struct ble_hci_ev_le_subev_biginfo_adv_report *e
693718
ev->max_pdu = (fields_buf >> 24) & 0xFF;
694719

695720
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;
721+
put_le24(ev->sdu_interval, fields_buf & 0x0FFFFF);
699722
ev->max_sdu = (fields_buf >> 20) & 0x0FFF;
700723

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

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

705736
if (biginfo_len == BLE_LL_SYNC_BIGINFO_LEN_ENC) {
706737
ev->encryption = 1;
@@ -712,25 +743,42 @@ ble_ll_sync_parse_biginfo_to_ev(struct ble_hci_ev_le_subev_biginfo_adv_report *e
712743
static void
713744
ble_ll_sync_send_biginfo_adv_rpt(struct ble_ll_sync_sm *sm, const uint8_t *biginfo, uint8_t biginfo_len)
714745
{
715-
struct ble_hci_ev_le_subev_biginfo_adv_report *ev;
746+
struct ble_hci_ev_le_subev_biginfo_adv_report ev;
716747
struct ble_hci_ev *hci_ev;
717748

718749
if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_BIGINFO_ADV_REPORT)) {
719750
return;
720751
}
721752

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

727777
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);
778+
hci_ev->length = sizeof(ev);
779+
ev.subev_code = BLE_HCI_LE_SUBEV_BIGINFO_ADV_REPORT;
780+
ev.sync_handle = htole16(ble_ll_sync_get_handle(sm));
781+
memcpy(hci_ev->data, &ev, sizeof(ev));
734782

735783
ble_ll_hci_event_send(hci_ev);
736784
}

0 commit comments

Comments
 (0)