Bluetooth: controller: Implement LE Create BIG Test command
Implement test version of the LE Create BIG command ll_big_test_create (BT_HCI_OP_LE_CREATE_BIG_TEST) in the controller. This enables use of CONFIG_BT_ISO_ADVANCED, which supports use of the following BIG/QoS configuration parameters (otherwise derived): - ISO_Interval - NSE - Max_PDU - BN - IRC - PTO Signed-off-by: Morten Priess <mtpr@oticon.com>
This commit is contained in:
parent
7bf2d8ff46
commit
2f1a254eae
1 changed files with 160 additions and 101 deletions
|
@ -86,11 +86,13 @@ static struct lll_adv_iso_stream
|
|||
stream_pool[CONFIG_BT_CTLR_ADV_ISO_STREAM_COUNT];
|
||||
static void *stream_free;
|
||||
|
||||
uint8_t ll_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
|
||||
uint32_t sdu_interval, uint16_t max_sdu,
|
||||
uint16_t max_latency, uint8_t rtn, uint8_t phy,
|
||||
uint8_t packing, uint8_t framing, uint8_t encryption,
|
||||
uint8_t *bcode)
|
||||
static uint8_t big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
|
||||
uint32_t sdu_interval, uint16_t max_sdu,
|
||||
uint16_t max_latency, uint8_t rtn, uint8_t phy,
|
||||
uint8_t packing, uint8_t framing, uint8_t encryption,
|
||||
uint8_t *bcode,
|
||||
uint16_t iso_interval, uint8_t nse, uint16_t max_pdu,
|
||||
uint8_t bn, uint8_t irc, uint8_t pto, bool test_config)
|
||||
{
|
||||
uint8_t hdr_data[1 + sizeof(uint8_t *)];
|
||||
struct lll_adv_sync *lll_adv_sync;
|
||||
|
@ -118,7 +120,6 @@ uint8_t ll_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
|
|||
uint8_t *acad;
|
||||
uint32_t ret;
|
||||
uint8_t err;
|
||||
uint8_t bn;
|
||||
int res;
|
||||
|
||||
adv_iso = adv_iso_get(big_handle);
|
||||
|
@ -156,14 +157,6 @@ uint8_t ll_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
|
|||
return BT_HCI_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (max_latency > 0x0FA0) {
|
||||
return BT_HCI_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (rtn > 0x0F) {
|
||||
return BT_HCI_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (phy > (BT_HCI_LE_EXT_SCAN_PHY_1M |
|
||||
BT_HCI_LE_EXT_SCAN_PHY_2M |
|
||||
BT_HCI_LE_EXT_SCAN_PHY_CODED)) {
|
||||
|
@ -181,6 +174,45 @@ uint8_t ll_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
|
|||
if (encryption > 1U) {
|
||||
return BT_HCI_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (test_config) {
|
||||
if (!IN_RANGE(iso_interval, 0x0004, 0x0C80)) {
|
||||
return BT_HCI_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (!IN_RANGE(nse, 0x01, 0x1F)) {
|
||||
return BT_HCI_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (!IN_RANGE(max_pdu, 0x01, MIN(0xFB, LL_BIS_OCTETS_TX_MAX))) {
|
||||
return BT_HCI_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (!IN_RANGE(bn, 0x01, 0x07)) {
|
||||
return BT_HCI_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (!IN_RANGE(irc, 0x01, 0x07)) {
|
||||
return BT_HCI_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
/* FIXME: PTO is currently limited to BN */
|
||||
if (!IN_RANGE(pto, 0x00, bn /*0x0F*/)) {
|
||||
return BT_HCI_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (bn * irc + pto < nse) {
|
||||
return BT_HCI_ERR_INVALID_PARAM;
|
||||
}
|
||||
} else {
|
||||
if (max_latency > 0x0FA0) {
|
||||
return BT_HCI_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (rtn > 0x0F) {
|
||||
return BT_HCI_ERR_INVALID_PARAM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if free BISes available */
|
||||
|
@ -276,7 +308,6 @@ uint8_t ll_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
|
|||
/* TODO: Move parameters to ULL if only accessed by ULL */
|
||||
lll_adv_iso = &adv_iso->lll;
|
||||
lll_adv_iso->handle = big_handle;
|
||||
lll_adv_iso->max_pdu = MIN(LL_BIS_OCTETS_TX_MAX, max_sdu);
|
||||
lll_adv_iso->phy = phy;
|
||||
lll_adv_iso->phy_flags = PHY_FLAGS_S8;
|
||||
|
||||
|
@ -304,31 +335,43 @@ uint8_t ll_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
|
|||
adv_iso_stream_handle_get(stream);
|
||||
}
|
||||
|
||||
/* FIXME: SDU per max latency */
|
||||
sdu_per_event = MAX((max_latency * USEC_PER_MSEC / sdu_interval), 2U) -
|
||||
1U;
|
||||
|
||||
/* BN (Burst Count), Mandatory BN = 1 */
|
||||
bn = DIV_ROUND_UP(max_sdu, lll_adv_iso->max_pdu) * sdu_per_event;
|
||||
if (bn > PDU_BIG_BN_MAX) {
|
||||
/* Restrict each BIG event to maximum burst per BIG event */
|
||||
lll_adv_iso->bn = PDU_BIG_BN_MAX;
|
||||
|
||||
/* Ceil the required burst count per SDU to next maximum burst
|
||||
* per BIG event.
|
||||
*/
|
||||
bn = DIV_ROUND_UP(bn, PDU_BIG_BN_MAX) * PDU_BIG_BN_MAX;
|
||||
} else {
|
||||
if (test_config) {
|
||||
lll_adv_iso->bn = bn;
|
||||
}
|
||||
lll_adv_iso->iso_interval = iso_interval;
|
||||
lll_adv_iso->irc = irc;
|
||||
lll_adv_iso->nse = nse;
|
||||
lll_adv_iso->max_pdu = max_pdu;
|
||||
iso_interval_us = iso_interval * PERIODIC_INT_UNIT_US;
|
||||
|
||||
/* Calculate ISO interval */
|
||||
/* iso_interval shall be at least SDU interval,
|
||||
* or integer multiple of SDU interval for unframed PDUs
|
||||
*/
|
||||
iso_interval_us = ((sdu_interval * lll_adv_iso->bn * sdu_per_event) /
|
||||
(bn * PERIODIC_INT_UNIT_US)) * PERIODIC_INT_UNIT_US;
|
||||
lll_adv_iso->iso_interval = iso_interval_us / PERIODIC_INT_UNIT_US;
|
||||
} else {
|
||||
lll_adv_iso->max_pdu = MIN(LL_BIS_OCTETS_TX_MAX, max_sdu);
|
||||
|
||||
/* FIXME: SDU per max latency */
|
||||
sdu_per_event = MAX((max_latency * USEC_PER_MSEC / sdu_interval), 2U) -
|
||||
1U;
|
||||
|
||||
/* BN (Burst Count), Mandatory BN = 1 */
|
||||
bn = DIV_ROUND_UP(max_sdu, lll_adv_iso->max_pdu) * sdu_per_event;
|
||||
if (bn > PDU_BIG_BN_MAX) {
|
||||
/* Restrict each BIG event to maximum burst per BIG event */
|
||||
lll_adv_iso->bn = PDU_BIG_BN_MAX;
|
||||
|
||||
/* Ceil the required burst count per SDU to next maximum burst
|
||||
* per BIG event.
|
||||
*/
|
||||
bn = DIV_ROUND_UP(bn, PDU_BIG_BN_MAX) * PDU_BIG_BN_MAX;
|
||||
} else {
|
||||
lll_adv_iso->bn = bn;
|
||||
}
|
||||
|
||||
/* Calculate ISO interval */
|
||||
/* iso_interval shall be at least SDU interval,
|
||||
* or integer multiple of SDU interval for unframed PDUs
|
||||
*/
|
||||
iso_interval_us = ((sdu_interval * lll_adv_iso->bn * sdu_per_event) /
|
||||
(bn * PERIODIC_INT_UNIT_US)) * PERIODIC_INT_UNIT_US;
|
||||
lll_adv_iso->iso_interval = iso_interval_us / PERIODIC_INT_UNIT_US;
|
||||
}
|
||||
|
||||
/* Calculate max available ISO event spacing */
|
||||
slot_overhead = HAL_TICKER_TICKS_TO_US(ticks_slot_overhead);
|
||||
|
@ -338,42 +381,50 @@ uint8_t ll_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
|
|||
event_spacing_max = 0U;
|
||||
}
|
||||
|
||||
ll_big_create_rtn_retry:
|
||||
/* Immediate Repetition Count (IRC), Mandatory IRC = 1 */
|
||||
lll_adv_iso->irc = rtn + 1U;
|
||||
/* Negotiate event spacing */
|
||||
do {
|
||||
if (!test_config) {
|
||||
/* Immediate Repetition Count (IRC), Mandatory IRC = 1 */
|
||||
lll_adv_iso->irc = rtn + 1U;
|
||||
|
||||
/* Calculate NSE (No. of Sub Events), Mandatory NSE = 1,
|
||||
* without PTO added.
|
||||
*/
|
||||
lll_adv_iso->nse = lll_adv_iso->bn * lll_adv_iso->irc;
|
||||
/* Calculate NSE (No. of Sub Events), Mandatory NSE = 1,
|
||||
* without PTO added.
|
||||
*/
|
||||
lll_adv_iso->nse = lll_adv_iso->bn * lll_adv_iso->irc;
|
||||
}
|
||||
|
||||
/* NOTE: Calculate sub_interval, if interleaved then it is Num_BIS x
|
||||
* BIS_Spacing (by BT Spec.)
|
||||
* else if sequential, then by our implementation, lets keep it
|
||||
* max_tx_time for Max_PDU + tMSS.
|
||||
*/
|
||||
lll_adv_iso->sub_interval = PDU_BIS_US(lll_adv_iso->max_pdu, encryption,
|
||||
phy, lll_adv_iso->phy_flags) +
|
||||
EVENT_MSS_US;
|
||||
ctrl_spacing = PDU_BIS_US(sizeof(struct pdu_big_ctrl), encryption, phy,
|
||||
lll_adv_iso->phy_flags);
|
||||
latency_packing = lll_adv_iso->sub_interval * lll_adv_iso->nse *
|
||||
lll_adv_iso->num_bis;
|
||||
event_spacing = latency_packing + ctrl_spacing +
|
||||
EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US;
|
||||
/* NOTE: Calculate sub_interval, if interleaved then it is Num_BIS x
|
||||
* BIS_Spacing (by BT Spec.)
|
||||
* else if sequential, then by our implementation, lets keep it
|
||||
* max_tx_time for Max_PDU + tMSS.
|
||||
*/
|
||||
lll_adv_iso->sub_interval = PDU_BIS_US(lll_adv_iso->max_pdu, encryption,
|
||||
phy, lll_adv_iso->phy_flags) +
|
||||
EVENT_MSS_US;
|
||||
ctrl_spacing = PDU_BIS_US(sizeof(struct pdu_big_ctrl), encryption, phy,
|
||||
lll_adv_iso->phy_flags);
|
||||
latency_packing = lll_adv_iso->sub_interval * lll_adv_iso->nse *
|
||||
lll_adv_iso->num_bis;
|
||||
event_spacing = latency_packing + ctrl_spacing +
|
||||
EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US;
|
||||
|
||||
/* Check if ISO interval too small to fit the calculated BIG event
|
||||
* timing required for the supplied BIG create parameters.
|
||||
*/
|
||||
if (event_spacing > event_spacing_max) {
|
||||
/* Check if we can reduce RTN to meet eventing spacing */
|
||||
if (!test_config && rtn) {
|
||||
rtn--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (event_spacing > event_spacing_max);
|
||||
|
||||
/* Check if ISO interval too small to fit the calculated BIG event
|
||||
* timing required for the supplied BIG create parameters.
|
||||
*/
|
||||
if (event_spacing > event_spacing_max) {
|
||||
|
||||
/* Check if we can reduce RTN to meet eventing spacing */
|
||||
if (rtn) {
|
||||
rtn--;
|
||||
|
||||
goto ll_big_create_rtn_retry;
|
||||
}
|
||||
|
||||
/* Release allocated link buffers */
|
||||
ll_rx_link_release(link_cmplt);
|
||||
ll_rx_link_release(link_term);
|
||||
|
@ -381,29 +432,34 @@ ll_big_create_rtn_retry:
|
|||
return BT_HCI_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (test_config) {
|
||||
lll_adv_iso->pto = pto;
|
||||
|
||||
} else {
|
||||
lll_adv_iso->ptc = ptc_calc(lll_adv_iso, event_spacing,
|
||||
event_spacing_max);
|
||||
|
||||
/* Pre-Transmission Offset (PTO) */
|
||||
if (lll_adv_iso->ptc) {
|
||||
lll_adv_iso->pto = bn / lll_adv_iso->bn;
|
||||
} else {
|
||||
lll_adv_iso->pto = 0U;
|
||||
}
|
||||
|
||||
/* Make room for pre-transmissions */
|
||||
lll_adv_iso->nse += lll_adv_iso->ptc;
|
||||
}
|
||||
|
||||
/* Based on packing requested, sequential or interleaved */
|
||||
if (packing) {
|
||||
/* Interleaved Packing */
|
||||
lll_adv_iso->bis_spacing = lll_adv_iso->sub_interval;
|
||||
lll_adv_iso->ptc = ptc_calc(lll_adv_iso, event_spacing,
|
||||
event_spacing_max);
|
||||
lll_adv_iso->nse += lll_adv_iso->ptc;
|
||||
lll_adv_iso->sub_interval = lll_adv_iso->bis_spacing *
|
||||
lll_adv_iso->nse;
|
||||
lll_adv_iso->nse;
|
||||
} else {
|
||||
/* Sequential Packing */
|
||||
lll_adv_iso->ptc = ptc_calc(lll_adv_iso, event_spacing,
|
||||
event_spacing_max);
|
||||
lll_adv_iso->nse += lll_adv_iso->ptc;
|
||||
lll_adv_iso->bis_spacing = lll_adv_iso->sub_interval *
|
||||
lll_adv_iso->nse;
|
||||
}
|
||||
|
||||
/* Pre-Transmission Offset (PTO) */
|
||||
if (lll_adv_iso->ptc) {
|
||||
lll_adv_iso->pto = bn / lll_adv_iso->bn;
|
||||
} else {
|
||||
lll_adv_iso->pto = 0U;
|
||||
lll_adv_iso->nse;
|
||||
}
|
||||
|
||||
/* TODO: Group count, GC = NSE / BN; PTO = GC - IRC;
|
||||
|
@ -588,6 +644,23 @@ ll_big_create_rtn_retry:
|
|||
return BT_HCI_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t ll_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
|
||||
uint32_t sdu_interval, uint16_t max_sdu,
|
||||
uint16_t max_latency, uint8_t rtn, uint8_t phy,
|
||||
uint8_t packing, uint8_t framing, uint8_t encryption,
|
||||
uint8_t *bcode)
|
||||
{
|
||||
return big_create(big_handle, adv_handle, num_bis, sdu_interval, max_sdu,
|
||||
max_latency, rtn, phy, packing, framing, encryption, bcode,
|
||||
0 /*iso_interval*/,
|
||||
0 /*nse*/,
|
||||
0 /*max_pdu*/,
|
||||
0 /*bn*/,
|
||||
0 /*irc*/,
|
||||
0 /*pto*/,
|
||||
false);
|
||||
}
|
||||
|
||||
uint8_t ll_big_test_create(uint8_t big_handle, uint8_t adv_handle,
|
||||
uint8_t num_bis, uint32_t sdu_interval,
|
||||
uint16_t iso_interval, uint8_t nse, uint16_t max_sdu,
|
||||
|
@ -595,25 +668,11 @@ uint8_t ll_big_test_create(uint8_t big_handle, uint8_t adv_handle,
|
|||
uint8_t framing, uint8_t bn, uint8_t irc,
|
||||
uint8_t pto, uint8_t encryption, uint8_t *bcode)
|
||||
{
|
||||
/* TODO: Implement */
|
||||
ARG_UNUSED(big_handle);
|
||||
ARG_UNUSED(adv_handle);
|
||||
ARG_UNUSED(num_bis);
|
||||
ARG_UNUSED(sdu_interval);
|
||||
ARG_UNUSED(iso_interval);
|
||||
ARG_UNUSED(nse);
|
||||
ARG_UNUSED(max_sdu);
|
||||
ARG_UNUSED(max_pdu);
|
||||
ARG_UNUSED(phy);
|
||||
ARG_UNUSED(packing);
|
||||
ARG_UNUSED(framing);
|
||||
ARG_UNUSED(bn);
|
||||
ARG_UNUSED(irc);
|
||||
ARG_UNUSED(pto);
|
||||
ARG_UNUSED(encryption);
|
||||
ARG_UNUSED(bcode);
|
||||
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
return big_create(big_handle, adv_handle, num_bis, sdu_interval, max_sdu,
|
||||
0 /*max_latency*/,
|
||||
0 /*rtn*/,
|
||||
phy, packing, framing, encryption, bcode,
|
||||
iso_interval, nse, max_pdu, bn, irc, pto, true);
|
||||
}
|
||||
|
||||
uint8_t ll_big_terminate(uint8_t big_handle, uint8_t reason)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue