Skip to content

Commit dae0e40

Browse files
committed
nimble/ll: Add PA ADI support
This adds ADI support for Periodic Advertising in controller.
1 parent 77902be commit dae0e40

File tree

7 files changed

+153
-30
lines changed

7 files changed

+153
-30
lines changed

nimble/controller/include/controller/ble_ll_sync.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ int ble_ll_sync_transfer(const uint8_t *cmdbuf, uint8_t len,
4545
uint8_t *rspbuf, uint8_t *rsplen);
4646

4747
void ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm,
48-
const uint8_t *sync_ind, bool reports_disabled,
48+
const uint8_t *sync_ind, uint8_t mode,
4949
uint16_t max_skip, uint32_t sync_timeout);
5050
void ble_ll_sync_transfer_disconnected(struct ble_ll_conn_sm *connsm);
5151

nimble/controller/src/ble_ll.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1935,6 +1935,10 @@ ble_ll_init(void)
19351935
features |= BLE_LL_FEAT_CS_PCT_QUALITY_IND;
19361936
#endif
19371937

1938+
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT)
1939+
features |= BLE_LL_FEAT_PERIODIC_ADV_ADI;
1940+
#endif
1941+
19381942
lldata->ll_supp_features = features;
19391943

19401944
/* Initialize random number generation */

nimble/controller/src/ble_ll_adv.c

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ struct ble_ll_adv_sm
167167
uint8_t periodic_adv_active : 1;
168168
uint8_t periodic_sync_active : 1;
169169
uint8_t periodic_sync_index : 1;
170+
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT)
171+
uint8_t periodic_include_adi : 1;
172+
uint16_t periodic_adv_adi;
173+
#endif
170174
uint8_t periodic_num_used_chans;
171175
uint8_t periodic_chanmap[BLE_LL_CHAN_MAP_LEN];
172176
uint16_t periodic_adv_itvl;
@@ -2175,6 +2179,12 @@ ble_ll_adv_sync_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte)
21752179
dptr += 1;
21762180
}
21772181
#endif
2182+
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT)
2183+
if (sync->ext_hdr_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) {
2184+
put_le16(dptr, advsm->periodic_adv_adi);
2185+
dptr += BLE_LL_EXT_ADV_DATA_INFO_SIZE;
2186+
}
2187+
#endif
21782188

21792189
if (sync->ext_hdr_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) {
21802190
if (!SYNC_NEXT(advsm)->sch.enqueued) {
@@ -2356,6 +2366,13 @@ ble_ll_adv_sync_calculate(struct ble_ll_adv_sm *advsm,
23562366

23572367
ext_hdr_len = BLE_LL_EXT_ADV_HDR_LEN;
23582368

2369+
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT)
2370+
if (advsm->periodic_include_adi) {
2371+
sync->ext_hdr_flags |= (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT);
2372+
ext_hdr_len += BLE_LL_EXT_ADV_DATA_INFO_SIZE;
2373+
}
2374+
#endif
2375+
23592376
/* TxPower if configured
23602377
* Note: TxPower shall not be present in chain PDU for SYNC
23612378
*/
@@ -2613,6 +2630,9 @@ ble_ll_adv_update_periodic_data(struct ble_ll_adv_sm *advsm)
26132630
os_mbuf_free_chain(advsm->periodic_adv_data);
26142631
advsm->periodic_adv_data = advsm->periodic_new_data;
26152632
advsm->periodic_new_data = NULL;
2633+
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT)
2634+
advsm->periodic_adv_adi = ble_ll_adv_update_did(advsm->periodic_adv_adi);
2635+
#endif
26162636
}
26172637

26182638
ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_NEW_DATA);
@@ -2679,6 +2699,14 @@ ble_ll_adv_sm_start_periodic(struct ble_ll_adv_sm *advsm)
26792699
*/
26802700
advsm->adi = ble_ll_adv_update_did(advsm->adi);
26812701

2702+
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT)
2703+
/*
2704+
* Since periodic advertising can be started without data we initialize DID here
2705+
* instead of after setting periodic advertising data.
2706+
*/
2707+
advsm->periodic_adv_adi = ble_ll_adv_update_did(advsm->periodic_adv_adi);
2708+
#endif
2709+
26822710
advsm->periodic_adv_active = 1;
26832711

26842712
/* keep channel map since we cannot change it later on */
@@ -3636,6 +3664,9 @@ ble_ll_adv_ext_set_param(const uint8_t *cmdbuf, uint8_t len,
36363664
advsm->sec_phy = cmd->sec_phy;
36373665
/* Update SID only */
36383666
advsm->adi = (advsm->adi & 0x0fff) | ((cmd->sid << 12));
3667+
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT)
3668+
advsm->periodic_adv_adi = (advsm->periodic_adv_adi & 0x0fff) | ((cmd->sid << 12));
3669+
#endif
36393670

36403671
advsm->props = props;
36413672

@@ -4141,6 +4172,23 @@ ble_ll_adv_periodic_set_data(const uint8_t *cmdbuf, uint8_t len)
41414172
case BLE_HCI_LE_SET_DATA_OPER_COMPLETE:
41424173
new_data = true;
41434174
break;
4175+
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT)
4176+
case BLE_HCI_LE_SET_DATA_OPER_UNCHANGED:
4177+
if (!advsm->periodic_adv_enabled) {
4178+
return BLE_ERR_INV_HCI_CMD_PARMS;
4179+
}
4180+
4181+
if (advsm->periodic_adv_data->om_len == 0) {
4182+
return BLE_ERR_INV_HCI_CMD_PARMS;
4183+
}
4184+
4185+
if (cmd->adv_data_len != 0) {
4186+
return BLE_ERR_INV_HCI_CMD_PARMS;
4187+
}
4188+
4189+
advsm->periodic_adv_adi = ble_ll_adv_update_did(advsm->periodic_adv_adi);
4190+
return BLE_ERR_SUCCESS;
4191+
#endif
41444192
default:
41454193
return BLE_ERR_INV_HCI_CMD_PARMS;
41464194
}
@@ -4217,10 +4265,14 @@ ble_ll_adv_periodic_enable(const uint8_t *cmdbuf, uint8_t len)
42174265
return BLE_ERR_UNK_ADV_INDENT;
42184266
}
42194267

4220-
#if MYNEWT_VAL(BLE_VERSION) >= 53
4268+
#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT)
42214269
if (cmd->enable & 0x02) {
42224270
return BLE_ERR_UNSUPPORTED;
4223-
} else if (cmd->enable & 0xfc) {
4271+
}
4272+
#endif
4273+
4274+
#if MYNEWT_VAL(BLE_VERSION) >= 53
4275+
if (cmd->enable & 0xfc) {
42244276
return BLE_ERR_INV_HCI_CMD_PARMS;
42254277
}
42264278
#else
@@ -4229,7 +4281,7 @@ ble_ll_adv_periodic_enable(const uint8_t *cmdbuf, uint8_t len)
42294281
}
42304282
#endif
42314283

4232-
if (cmd->enable) {
4284+
if (cmd->enable & 0x1) {
42334285
if (advsm->props & (BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV |
42344286
BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE |
42354287
BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE |
@@ -4247,7 +4299,7 @@ ble_ll_adv_periodic_enable(const uint8_t *cmdbuf, uint8_t len)
42474299

42484300
/* If Enable is set to 0x01 and the length of the periodic advertising
42494301
* data is greater than the maximum that the Controller can transmit
4250-
* within the chosen periodicadvertising interval, the Controller shall
4302+
* within the chosen periodic advertising interval, the Controller shall
42514303
* return the error code Packet Too Long (0x45).
42524304
*/
42534305
if (!ble_ll_adv_periodic_check_data_itvl(SYNC_DATA_LEN(advsm),
@@ -4257,6 +4309,10 @@ ble_ll_adv_periodic_enable(const uint8_t *cmdbuf, uint8_t len)
42574309
return BLE_ERR_PACKET_TOO_LONG;
42584310
}
42594311

4312+
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT)
4313+
advsm->periodic_include_adi = !!(cmd->enable & 0x2);
4314+
#endif
4315+
42604316
/* If the advertising set is not currently enabled (see the
42614317
* LE_Set_Extended_Advertising_Enable command), the periodic advertising
42624318
* is not started until the advertising set is enabled.

nimble/controller/src/ble_ll_conn_hci.c

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2069,11 +2069,18 @@ ble_ll_set_sync_transfer_params(const uint8_t *cmdbuf, uint8_t len,
20692069
goto done;
20702070
}
20712071

2072-
if ((MYNEWT_VAL(BLE_VERSION) >= 53 ) && (cmd->mode == 0x03)) {
2073-
/* We do not support ADI in periodic advertising thus cannot enable
2074-
* duplicate filtering.
2075-
*/
2076-
return BLE_ERR_UNSUPPORTED;
2072+
if (MYNEWT_VAL(BLE_VERSION) >= 53) {
2073+
if (cmd->mode > 0x03) {
2074+
return BLE_ERR_INV_HCI_CMD_PARMS;
2075+
}
2076+
2077+
if ((cmd->mode == 0x03) &&
2078+
!MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT)) {
2079+
/* We do not support ADI in periodic advertising thus cannot enable
2080+
* duplicate filtering.
2081+
*/
2082+
return BLE_ERR_UNSUPPORTED;
2083+
}
20772084
} else if (cmd->mode > 0x02) {
20782085
return BLE_ERR_INV_HCI_CMD_PARMS;
20792086
}
@@ -2126,11 +2133,18 @@ ble_ll_set_default_sync_transfer_params(const uint8_t *cmdbuf, uint8_t len)
21262133
return BLE_ERR_INV_HCI_CMD_PARMS;
21272134
}
21282135

2129-
if ((MYNEWT_VAL(BLE_VERSION) >= 53 ) && (cmd->mode == 0x03)) {
2130-
/* We do not support ADI in periodic advertising thus cannot enable
2131-
* duplicate filtering.
2132-
*/
2133-
return BLE_ERR_UNSUPPORTED;
2136+
if (MYNEWT_VAL(BLE_VERSION) >= 53) {
2137+
if (cmd->mode > 0x03) {
2138+
return BLE_ERR_INV_HCI_CMD_PARMS;
2139+
}
2140+
2141+
if ((cmd->mode == 0x03) &&
2142+
!MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT)) {
2143+
/* We do not support ADI in periodic advertising thus cannot enable
2144+
* duplicate filtering.
2145+
*/
2146+
return BLE_ERR_UNSUPPORTED;
2147+
}
21342148
} else if (cmd->mode > 0x02) {
21352149
return BLE_ERR_INV_HCI_CMD_PARMS;
21362150
}

nimble/controller/src/ble_ll_ctrl.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,11 +1135,9 @@ ble_ll_ctrl_rx_phy_update_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
11351135
static uint8_t
11361136
ble_ll_ctrl_rx_periodic_sync_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
11371137
{
1138-
if (connsm->sync_transfer_mode) {
1139-
ble_ll_sync_periodic_ind(connsm, dptr, connsm->sync_transfer_mode == 1,
1140-
connsm->sync_transfer_skip,
1141-
connsm->sync_transfer_sync_timeout);
1142-
}
1138+
ble_ll_sync_periodic_ind(connsm, dptr, connsm->sync_transfer_mode,
1139+
connsm->sync_transfer_skip,
1140+
connsm->sync_transfer_sync_timeout);
11431141
return BLE_ERR_MAX;
11441142
}
11451143
#endif

nimble/controller/src/ble_ll_sync.c

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
#define BLE_LL_SYNC_SM_FLAG_HCI_TRUNCATED 0x0100
6565
#define BLE_LL_SYNC_SM_FLAG_NEW_CHANMAP 0x0200
6666
#define BLE_LL_SYNC_SM_FLAG_CHAIN 0x0400
67+
#define BLE_LL_SYNC_SM_FLAG_DUPLICATES 0x0800
6768

6869
#define BLE_LL_SYNC_ITVL_USECS 1250
6970

@@ -121,6 +122,10 @@ struct ble_ll_sync_sm {
121122
uint16_t event_cntr_last_received;
122123
uint8_t adv_addr_rpa[6];
123124
#endif
125+
126+
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT)
127+
uint16_t prev_adi;
128+
#endif
124129
};
125130

126131
static struct ble_ll_sync_sm g_ble_ll_sync_sm[BLE_LL_SYNC_CNT];
@@ -548,7 +553,7 @@ ble_ll_sync_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *rxhdr)
548553

549554
static int
550555
ble_ll_sync_parse_ext_hdr(struct os_mbuf *om, uint8_t **aux, int8_t *tx_power,
551-
uint8_t **acad, uint8_t *acad_len)
556+
uint8_t **acad, uint8_t *acad_len, uint16_t **adi)
552557
{
553558
uint8_t *rxbuf = om->om_data;
554559
uint8_t ext_hdr_flags;
@@ -587,8 +592,10 @@ ble_ll_sync_parse_ext_hdr(struct os_mbuf *om, uint8_t **aux, int8_t *tx_power,
587592
i += BLE_LL_EXT_ADV_CTE_INFO_SIZE;
588593
}
589594

590-
/* there should be no ADI in Sync or chain, skip it */
591595
if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) {
596+
if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT) {
597+
*adi = (uint16_t *) ext_hdr + i;
598+
}
592599
i += BLE_LL_EXT_ADV_DATA_INFO_SIZE;
593600
}
594601

@@ -1137,10 +1144,12 @@ ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
11371144
uint8_t *aux = NULL;
11381145
uint8_t *acad = NULL;
11391146
uint8_t acad_len = 0;
1147+
uint16_t *adi = NULL;
11401148
const uint8_t *biginfo = NULL;
11411149
uint8_t biginfo_len = 0;
11421150
int datalen;
11431151
bool reports_enabled;
1152+
bool is_duplicate = false;
11441153

11451154
BLE_LL_ASSERT(sm);
11461155

@@ -1186,14 +1195,22 @@ ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
11861195
}
11871196

11881197
/* get ext header data */
1189-
datalen = ble_ll_sync_parse_ext_hdr(rxpdu, &aux, &tx_power, &acad, &acad_len);
1198+
datalen = ble_ll_sync_parse_ext_hdr(rxpdu, &aux, &tx_power, &acad, &acad_len, &adi);
11901199
if (datalen < 0) {
11911200
/* we got bad packet, end event */
11921201
goto end_event;
11931202
}
11941203

1204+
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT)
1205+
if (adi != NULL) {
1206+
is_duplicate = (sm->flags & BLE_LL_SYNC_SM_FLAG_DUPLICATES) && (*adi == sm->prev_adi);
1207+
sm->prev_adi = *adi;
1208+
}
1209+
#endif
1210+
11951211
reports_enabled = ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT) &&
1196-
!(sm->flags & BLE_LL_SYNC_SM_FLAG_DISABLED);
1212+
!(sm->flags & BLE_LL_SYNC_SM_FLAG_DISABLED) &&
1213+
!is_duplicate;
11971214

11981215
/* no need to schedule for chain if reporting is disabled */
11991216
if (reports_enabled) {
@@ -1539,6 +1556,12 @@ ble_ll_sync_info_event(struct ble_ll_scan_addr_data *addrd,
15391556
}
15401557
#endif
15411558

1559+
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT)
1560+
if (g_ble_ll_sync_create_params.options & BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_DUPLICATES) {
1561+
sm->flags |= BLE_LL_SYNC_SM_FLAG_DUPLICATES;
1562+
}
1563+
#endif
1564+
15421565
sm->flags &= ~BLE_LL_SYNC_SM_FLAG_RESERVED;
15431566
sm->flags |= BLE_LL_SYNC_SM_FLAG_ESTABLISHING;
15441567
sm->flags |= BLE_LL_SYNC_SM_FLAG_SYNC_INFO;
@@ -1583,7 +1606,8 @@ ble_ll_sync_create(const uint8_t *cmdbuf, uint8_t len)
15831606
return BLE_ERR_INV_HCI_CMD_PARMS;
15841607
}
15851608
if (!(cmd->options & BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_DISABLED) &&
1586-
(cmd->options & BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_DUPLICATES)) {
1609+
(cmd->options & BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_DUPLICATES) &&
1610+
!MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT)) {
15871611
/* We do not support ADI in periodic advertising thus cannot enable
15881612
* duplicate filtering.
15891613
*/
@@ -1870,7 +1894,8 @@ ble_ll_sync_receive_enable(const uint8_t *cmdbuf, uint8_t len)
18701894
if (MYNEWT_VAL(BLE_VERSION) >= 53) {
18711895
if (cmd->enable > 0x03) {
18721896
return BLE_ERR_INV_HCI_CMD_PARMS;
1873-
} else if (cmd->enable == 0x03) {
1897+
} else if ((cmd->enable == 0x03) &&
1898+
!MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT)) {
18741899
/* We do not support ADI in periodic advertising thus cannot enable
18751900
* duplicate filtering.
18761901
*/
@@ -1898,8 +1923,14 @@ ble_ll_sync_receive_enable(const uint8_t *cmdbuf, uint8_t len)
18981923
return BLE_ERR_UNK_ADV_INDENT;
18991924
}
19001925

1901-
if (cmd->enable) {
1926+
if (cmd->enable & 0x1) {
19021927
sm->flags &= ~BLE_LL_SYNC_SM_FLAG_DISABLED;
1928+
1929+
if (cmd->enable & 0x2) {
1930+
sm->flags |= BLE_LL_SYNC_SM_FLAG_DUPLICATES;
1931+
} else {
1932+
sm->flags &= ~BLE_LL_SYNC_SM_FLAG_DUPLICATES;
1933+
}
19031934
} else {
19041935
sm->flags |= BLE_LL_SYNC_SM_FLAG_DISABLED;
19051936
}
@@ -1940,7 +1971,7 @@ ble_ll_sync_transfer_get(const uint8_t *addr, uint8_t addr_type, uint8_t sid)
19401971

19411972
void
19421973
ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm,
1943-
const uint8_t *sync_ind, bool reports_disabled,
1974+
const uint8_t *sync_ind, uint8_t mode,
19441975
uint16_t max_skip, uint32_t sync_timeout)
19451976
{
19461977
const uint8_t *syncinfo = sync_ind + 2;
@@ -1966,6 +1997,10 @@ ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm,
19661997
uint8_t sca;
19671998
os_sr_t sr;
19681999

2000+
if (!mode) {
2001+
return;
2002+
}
2003+
19692004
phy_mode = ble_ll_ctrl_phy_from_phy_mask(sync_ind[25]);
19702005
itvl = get_le16(syncinfo + 2);
19712006
/* ignore if sync params are not valid */
@@ -2133,8 +2168,15 @@ ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm,
21332168
sm->anchor_point = sm->sch.start_time + g_ble_ll_sched_offset_ticks;
21342169
sm->anchor_point_usecs = sm->sch.remainder;
21352170

2136-
if (reports_disabled) {
2171+
switch (mode) {
2172+
case 0x1:
21372173
sm->flags |= BLE_LL_SYNC_SM_FLAG_DISABLED;
2174+
break;
2175+
case 0x3:
2176+
sm->flags |= BLE_LL_SYNC_SM_FLAG_DUPLICATES;
2177+
break;
2178+
default:
2179+
break;
21382180
}
21392181
}
21402182

0 commit comments

Comments
 (0)