Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 60 additions & 12 deletions nimble/controller/src/ble_ll_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -673,11 +673,36 @@ ble_ll_sync_send_truncated_per_adv_rpt(struct ble_ll_sync_sm *sm, uint8_t *evbuf
}

#if MYNEWT_VAL(BLE_LL_PERIODIC_ADV_SYNC_BIGINFO_REPORTS)
static uint8_t
ble_ll_sync_biginfo_phy_get(const uint8_t *biginfo)
{
uint8_t phy;

phy = (biginfo[27] >> 5) & 0x07;

switch (phy) {
case 0:
return BLE_PHY_1M;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
case 1:
return BLE_PHY_2M;
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
case 2:
return BLE_PHY_CODED;
#endif
default:
return 0x00;
}
}

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;
uint8_t framing_mode;
uint8_t framed;

fields_buf = get_le32(&biginfo[0]);
ev->iso_interval = (fields_buf >> 15) & 0x0FFF;
Expand All @@ -693,14 +718,20 @@ ble_ll_sync_parse_biginfo_to_ev(struct ble_hci_ev_le_subev_biginfo_adv_report *e
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;
put_le24(ev->sdu_interval, fields_buf & 0x0FFFFF);
ev->max_sdu = (fields_buf >> 20) & 0x0FFF;

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

ev->framing = (biginfo[32] >> 7) & 0x01;
framed = (biginfo[32] >> 7) & 0x01;
framing_mode = (biginfo[12] >> 7) & 0x01;
if (framed && framing_mode) {
ev->framing = BLE_HCI_ISO_FRAMING_FRAMED_UNSEGMENTED;
} else if (framed) {
ev->framing = BLE_HCI_ISO_FRAMING_FRAMED_SEGMENTABLE;
} else {
ev->framing = BLE_HCI_ISO_FRAMING_UNFRAMED;
}

if (biginfo_len == BLE_LL_SYNC_BIGINFO_LEN_ENC) {
ev->encryption = 1;
Expand All @@ -712,25 +743,42 @@ ble_ll_sync_parse_biginfo_to_ev(struct ble_hci_ev_le_subev_biginfo_adv_report *e
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_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;
}

/* The BIGInfo length is 33 octets for an unencrypted BIG and 57 octets for an encrypted BIG. */
if (biginfo_len != BLE_LL_SYNC_BIGINFO_LEN &&
biginfo_len != BLE_LL_SYNC_BIGINFO_LEN_ENC) {
return;
}

memset(&ev, 0, sizeof(ev));
ble_ll_sync_parse_biginfo_to_ev(&ev, biginfo, biginfo_len);

if (!ev.phy) {
/* Core 6.0 | Vol 6, Part B, 4.4.5.2
* If the PHY field of the BIGInfo specifies a PHY that the Link Layer does not support or is
* reserved for future use, the Link Layer shall ignore the BIGInfo, shall not report the
* BIGInfo to the Host, and shall not enter the Synchronization state for the BIG specified
* in the BIGinfo.
*/
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);
hci_ev->length = sizeof(ev);
ev.subev_code = BLE_HCI_LE_SUBEV_BIGINFO_ADV_REPORT;
ev.sync_handle = htole16(ble_ll_sync_get_handle(sm));
memcpy(hci_ev->data, &ev, sizeof(ev));

ble_ll_hci_event_send(hci_ev);
}
Expand Down
Loading