Bluetooth: Controller: Integrate ISOAL for ISO Broadcast

- Include ISO stream count in ISO streams definitions in
  controller.
- Create ISOAL source on controller when ISO data path is
  setup.
- Send broadcast data buffers transferred from host over
  HCI to ISOAL as ISO SDU fragments.
- Allow bot conn and ISO data to use data_buf_overflow.
- Store ISO interval during BIG create.
- Remove ISO data path for each BIS during BIG terminate
  procedure.
- Set value (temporarily) for ISOAL target_event enabling
  it to Tx data.
- Check status of data fragment sent to ISOAL for memory
  allocation and other errors.
- Destroy ISOAL source when ISO stream released.
- Use ISO Advertising handle, not stream handle to destroy
  ISO data path.
- Remove extra ISOAL sink destroy call when removing ISO
  data path.
- Add FIXME comment as reminder to address LL_ASSERT on
  isoal_status error.

Signed-off-by: Carl Stehle <droid@appception.com>
Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
Carl Stehle 2022-11-07 11:17:37 -08:00 committed by Stephanos Ioannidis
commit 714f80d225
11 changed files with 272 additions and 196 deletions

View file

@ -5704,11 +5704,13 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt)
sdu_frag_tx.dbuf = buf->data;
sdu_frag_tx.size = len;
if (false) {
#if defined(CONFIG_BT_CTLR_CONN_ISO)
/* Extract source handle from CIS or BIS handle by way of header and
* data path
*/
if (IS_CIS_HANDLE(handle)) {
} else if (IS_CIS_HANDLE(handle)) {
struct ll_conn_iso_stream *cis =
ll_iso_stream_connected_get(handle);
if (!cis) {
@ -5763,13 +5765,13 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt)
/* TODO: Assign *evt if an immediate response is required */
return 0;
}
#endif /* CONFIG_BT_CTLR_CONN_ISO */
#if defined(CONFIG_BT_CTLR_ADV_ISO)
if (IS_ADV_ISO_HANDLE(handle)) {
/* FIXME: Use ISOAL */
struct node_tx_iso *tx;
} else if (IS_ADV_ISO_HANDLE(handle)) {
struct lll_adv_iso_stream *stream;
struct ll_adv_iso_set *adv_iso;
struct lll_adv_iso *lll_iso;
uint16_t stream_handle;
uint16_t slen;
@ -5783,79 +5785,53 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt)
}
/* Get BIS stream handle and stream context */
handle = bt_iso_handle(handle);
if (handle < BT_CTLR_ADV_ISO_STREAM_HANDLE_BASE) {
return -EINVAL;
}
stream_handle = LL_BIS_ADV_IDX_FROM_HANDLE(handle);
struct lll_adv_iso_stream *stream;
stream = ull_adv_iso_stream_get(stream_handle);
if (!stream) {
if (!stream || !stream->dp) {
LOG_ERR("Invalid BIS stream");
return -EINVAL;
}
struct ll_adv_iso_set *adv_iso;
adv_iso = ull_adv_iso_by_stream_get(stream_handle);
if (!adv_iso) {
LOG_ERR("No BIG associated with stream handle");
return -EINVAL;
}
/* Get free node tx */
tx = ll_iso_tx_mem_acquire();
if (!tx) {
LOG_ERR("ISO Tx Buffer Overflow");
data_buf_overflow(evt, BT_OVERFLOW_LINK_ISO);
return -ENOBUFS;
}
struct pdu_bis *pdu = (void *)tx->pdu;
/* FIXME: Update to use correct LLID for BIS and CIS */
switch (bt_iso_flags_pb(flags)) {
case BT_ISO_SINGLE:
pdu->ll_id = PDU_BIS_LLID_COMPLETE_END;
break;
default:
ll_iso_tx_mem_release(tx);
return -EINVAL;
}
pdu->len = slen;
memcpy(pdu->payload, buf->data, slen);
struct lll_adv_iso *lll_iso;
/* FIXME: convey group start */
sdu_frag_tx.grp_ref_point = 0;
/* FIXME: temporary interface to enable ISOAL data Tx
* Create provide proper interface between client
* (using ISOAL target_event) and ISOAL, preferably
* without dependence on peeking at LL data.
* Problem is that client must specify a value greater
* than LL bisPayloadCounter or no data is sent.
*/
lll_iso = &adv_iso->lll;
sdu_frag_tx.target_event = (lll_iso->payload_count / lll_iso->bn);
uint64_t pkt_seq_num;
/* Start Fragmentation */
/* FIXME: need to ensure ISO-AL returns proper isoal_status.
* Currently there are cases where ISO-AL calls LL_ASSERT.
*/
isoal_status_t isoal_status =
isoal_tx_sdu_fragment(stream->dp->source_hdl, &sdu_frag_tx);
pkt_seq_num = lll_iso->payload_count / lll_iso->bn;
if (((pkt_seq_num - stream->pkt_seq_num) & BIT64_MASK(39)) <=
BIT64_MASK(38)) {
stream->pkt_seq_num = pkt_seq_num;
} else {
pkt_seq_num = stream->pkt_seq_num;
}
if (isoal_status) {
if (isoal_status & ISOAL_STATUS_ERR_PDU_ALLOC) {
data_buf_overflow(evt, BT_OVERFLOW_LINK_ISO);
return -ENOBUFS;
}
tx->payload_count = pkt_seq_num * lll_iso->bn;
stream->pkt_seq_num++;
if (ll_iso_tx_mem_enqueue(handle, tx, NULL)) {
LOG_ERR("Invalid ISO Tx Enqueue");
ll_iso_tx_mem_release(tx);
return -EINVAL;
}
return 0;
}
#endif /* CONFIG_BT_CTLR_ADV_ISO */
}
return -EINVAL;
}
#endif /* CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_CONN_ISO */