Lines Matching +full:multi +full:- +full:functional

4  * SPDX-License-Identifier: Apache-2.0
100 * Zero-init entire ISO-AL state
109 * @brief Initialize ISO-AL
146 * @return Validity - valid if time_after leads time_before with
160 if ((time_before - time_after) <= ISOAL_TIME_SPAN_HALF_US) { in isoal_get_time_diff()
164 *result = time_after + ISOAL_TIME_SPAN_FULL_US - time_before; in isoal_get_time_diff()
172 *result = time_after - time_before; in isoal_get_time_diff()
197 * @brief Find free sink from statically-sized pool and allocate it
288 session->handle = handle; in isoal_sink_create()
289 session->framed = framed; in isoal_sink_create()
290 session->sdu_interval = sdu_interval; in isoal_sink_create()
291 session->iso_interval = iso_interval; in isoal_sink_create()
292 session->burst_number = burst_number; in isoal_sink_create()
299 session->pdus_per_sdu = (burst_number * sdu_interval) / in isoal_sink_create()
306 * C->P: SDU_Synchronization_Reference = in isoal_sink_create()
307 * CIS reference anchor point + CIS_Sync_Delay + (FT_C_To_P - 1) * ISO_Interval in isoal_sink_create()
309 * P->C: SDU_Synchronization_Reference = in isoal_sink_create()
310 * CIS reference anchor point + CIS_Sync_Delay - CIG_Sync_Delay - in isoal_sink_create()
311 * ((ISO_Interval / SDU interval)-1) * SDU interval in isoal_sink_create()
318 * C->P: SDU_Synchronization_Reference = in isoal_sink_create()
320 * CIS_Sync_Delay + SDU_Interval_C_To_P + FT_C_To_P * ISO_Interval - in isoal_sink_create()
323 * P->C: synchronization reference SDU = CIS reference anchor point + in isoal_sink_create()
324 * CIS_Sync_Delay - CIG_Sync_Delay - Time_Offset in isoal_sink_create()
328 * BIG_Sync_Delay + SDU_interval + ISO_Interval - Time_Offset. in isoal_sink_create()
332 session->sdu_sync_const = stream_sync_delay + sdu_interval + in isoal_sink_create()
335 session->sdu_sync_const = stream_sync_delay + in isoal_sink_create()
336 ((flush_timeout - 1UL) * iso_interval_us); in isoal_sink_create()
340 session->sdu_sync_const = stream_sync_delay - group_sync_delay; in isoal_sink_create()
342 session->sdu_sync_const = stream_sync_delay - group_sync_delay - in isoal_sink_create()
343 (((iso_interval_us / sdu_interval) - 1UL) * in isoal_sink_create()
348 session->sdu_sync_const = group_sync_delay + sdu_interval + iso_interval_us; in isoal_sink_create()
350 session->sdu_sync_const = group_sync_delay; in isoal_sink_create()
356 /* Remember the platform-specific callbacks */ in isoal_sink_create()
357 session->sdu_alloc = sdu_alloc; in isoal_sink_create()
358 session->sdu_emit = sdu_emit; in isoal_sink_create()
359 session->sdu_write = sdu_write; in isoal_sink_create()
362 session->sn = 0; in isoal_sink_create()
368 * @brief Atomically enable latch-in of packets and SDU production
386 * @brief Atomically disable latch-in of packets and SDU production
422 session = &sink->session; in isoal_rx_allocate_sdu()
423 sp = &sink->sdu_production; in isoal_rx_allocate_sdu()
424 sdu = &sp->sdu; in isoal_rx_allocate_sdu()
427 const bool sdu_complete = (sp->sdu_available == 0); in isoal_rx_allocate_sdu()
431 err = session->sdu_alloc( in isoal_rx_allocate_sdu()
434 &sdu->contents /* [out] Updated with pointer and size */ in isoal_rx_allocate_sdu()
438 sp->sdu_allocated = 1U; in isoal_rx_allocate_sdu()
442 sp->sdu_written = 0; in isoal_rx_allocate_sdu()
443 sp->sdu_available = sdu->contents.size; in isoal_rx_allocate_sdu()
444 LL_ASSERT(sdu->contents.size > 0); in isoal_rx_allocate_sdu()
447 sdu->sn = session->sn; in isoal_rx_allocate_sdu()
474 session = &sink->session; in isoal_rx_buffered_emit_sdu()
475 sp = &sink->sdu_production; in isoal_rx_buffered_emit_sdu()
476 sdu = &sp->sdu; in isoal_rx_buffered_emit_sdu()
479 sdu_frag.sdu_state = sp->sdu_state; in isoal_rx_buffered_emit_sdu()
480 sdu_frag.sdu_frag_size = sp->sdu_written; in isoal_rx_buffered_emit_sdu()
494 next_write_indx = sp->sdu_list.next_write_indx; in isoal_rx_buffered_emit_sdu()
507 * not the starting fragment of a multi-fragment SDU. in isoal_rx_buffered_emit_sdu()
533 sp->sdu_list.list[i].sdu_frag_size; in isoal_rx_buffered_emit_sdu()
534 if (sp->sdu_list.list[i].sdu.status == ISOAL_SDU_STATUS_LOST_DATA || in isoal_rx_buffered_emit_sdu()
539 sp->sdu_list.list[i].sdu.status; in isoal_rx_buffered_emit_sdu()
545 err |= session->sdu_emit(sink, &sp->sdu_list.list[i], in isoal_rx_buffered_emit_sdu()
549 next_write_indx = sp->sdu_list.next_write_indx = 0; in isoal_rx_buffered_emit_sdu()
562 err |= session->sdu_emit(sink, &sdu_frag, &sdu_status); in isoal_rx_buffered_emit_sdu()
566 sp->sdu_list.list[next_write_indx++] = sdu_frag; in isoal_rx_buffered_emit_sdu()
567 sp->sdu_list.next_write_indx = next_write_indx; in isoal_rx_buffered_emit_sdu()
585 sp = &sink->sdu_production; in isoal_rx_try_emit_sdu()
586 session = &sink->session; in isoal_rx_try_emit_sdu()
587 sdu = &sp->sdu; in isoal_rx_try_emit_sdu()
590 const bool sdu_complete = (sp->sdu_available == 0) || end_of_sdu; in isoal_rx_try_emit_sdu()
593 sp->sdu_available = 0; in isoal_rx_try_emit_sdu()
599 switch (sp->sdu_state) { in isoal_rx_try_emit_sdu()
602 sp->sdu_state = BT_ISO_SINGLE; in isoal_rx_try_emit_sdu()
605 sp->sdu_state = BT_ISO_START; in isoal_rx_try_emit_sdu()
611 sp->sdu_state = BT_ISO_END; in isoal_rx_try_emit_sdu()
614 sp->sdu_state = BT_ISO_CONT; in isoal_rx_try_emit_sdu()
619 sdu->status = sp->sdu_status; in isoal_rx_try_emit_sdu()
622 sp->sdu_allocated = 0U; in isoal_rx_try_emit_sdu()
626 sp->sdu_status = ISOAL_SDU_STATUS_VALID; in isoal_rx_try_emit_sdu()
627 session->sn++; in isoal_rx_try_emit_sdu()
631 sink->sdu_production.sdu_state = next_state; in isoal_rx_try_emit_sdu()
655 pdu_payload = pdu_meta->pdu->payload + offset; in isoal_rx_append_to_sdu()
674 sp = &sink->sdu_production; in isoal_rx_append_to_sdu()
675 sdu = &sp->sdu; in isoal_rx_append_to_sdu()
681 * - What can fit in the destination SDU. in isoal_rx_append_to_sdu()
682 * - What remains of the packet. in isoal_rx_append_to_sdu()
686 sp->sdu_available in isoal_rx_append_to_sdu()
690 const struct isoal_sink_session *session = &sink->session; in isoal_rx_append_to_sdu()
692 err |= session->sdu_write(sdu->contents.dbuf, in isoal_rx_append_to_sdu()
693 sp->sdu_written, in isoal_rx_append_to_sdu()
697 sp->sdu_written += consume_len; in isoal_rx_append_to_sdu()
698 sp->sdu_available -= consume_len; in isoal_rx_append_to_sdu()
699 packet_available -= consume_len; in isoal_rx_append_to_sdu()
705 if (sp->sdu_allocated) { in isoal_rx_append_to_sdu()
744 sp = &sink->sdu_production; in isoal_rx_unframed_consume()
745 session = &sink->session; in isoal_rx_unframed_consume()
746 meta = pdu_meta->meta; in isoal_rx_unframed_consume()
747 pdu = pdu_meta->pdu; in isoal_rx_unframed_consume()
753 llid = pdu->ll_id; in isoal_rx_unframed_consume()
754 pdu_err = (pdu_meta->meta->status != ISOAL_PDU_STATUS_VALID); in isoal_rx_unframed_consume()
755 length = pdu_err ? 0U : pdu->len; in isoal_rx_unframed_consume()
757 * However if there are errors in the PDU, it could be an incorrectly receive non-padding in isoal_rx_unframed_consume()
762 (!pdu_err || sp->fsm == ISOAL_ERR_SPOOL); in isoal_rx_unframed_consume()
763 seq_err = (meta->payload_number != (sp->prev_pdu_id+1)); in isoal_rx_unframed_consume()
765 /* If there are no buffers available, the PDUs received by the ISO-AL in isoal_rx_unframed_consume()
770 if (sp->fsm == ISOAL_ERR_SPOOL) { in isoal_rx_unframed_consume()
777 ((sp->prev_pdu_is_end || sp->prev_pdu_is_padding) && in isoal_rx_unframed_consume()
786 || (meta->payload_number % session->pdus_per_sdu == 0)) { in isoal_rx_unframed_consume()
790 sp->fsm = ISOAL_START; in isoal_rx_unframed_consume()
794 if (sp->fsm == ISOAL_START) { in isoal_rx_unframed_consume()
800 sp->sdu_status = ISOAL_SDU_STATUS_VALID; in isoal_rx_unframed_consume()
801 sp->sdu_state = BT_ISO_START; in isoal_rx_unframed_consume()
802 sp->pdu_cnt = 1; in isoal_rx_unframed_consume()
803 sp->only_padding = pdu_padding; in isoal_rx_unframed_consume()
810 * BT Core V5.3 : Vol 6 Low Energy Controller : Part G IS0-AL: in isoal_rx_unframed_consume()
821 anchorpoint = meta->timestamp; in isoal_rx_unframed_consume()
822 latency = session->sdu_sync_const; in isoal_rx_unframed_consume()
823 sdu = &sp->sdu; in isoal_rx_unframed_consume()
824 sdu->timestamp = isoal_get_wrapped_time_us(anchorpoint, latency); in isoal_rx_unframed_consume()
830 * BT Core V5.3 : Vol 6 Low Energy Controller : Part G IS0-AL: in isoal_rx_unframed_consume()
840 sdu_offset = (meta->payload_number % session->burst_number) / session->pdus_per_sdu; in isoal_rx_unframed_consume()
841 sdu->timestamp = isoal_get_wrapped_time_us(sdu->timestamp, in isoal_rx_unframed_consume()
842 sdu_offset * session->sdu_interval); in isoal_rx_unframed_consume()
844 sp->pdu_cnt++; in isoal_rx_unframed_consume()
847 last_pdu = (sp->pdu_cnt == session->pdus_per_sdu); in isoal_rx_unframed_consume()
849 sp->only_padding = sp->only_padding && pdu_padding; in isoal_rx_unframed_consume()
851 switch (sp->fsm) { in isoal_rx_unframed_consume()
918 * https://bluetooth.atlassian.net/browse/ES-22876 in isoal_rx_unframed_consume()
919 * Request for Clarification - Recombination actions when only in isoal_rx_unframed_consume()
931 sp->sdu_status |= ISOAL_SDU_STATUS_LOST_DATA; in isoal_rx_unframed_consume()
933 sp->sdu_status |= meta->status; in isoal_rx_unframed_consume()
934 } else if (last_pdu && sp->only_padding) { in isoal_rx_unframed_consume()
936 sp->sdu_status |= ISOAL_SDU_STATUS_LOST_DATA; in isoal_rx_unframed_consume()
938 (sp->fsm != ISOAL_ERR_SPOOL)) { in isoal_rx_unframed_consume()
940 sp->sdu_status |= ISOAL_SDU_STATUS_ERRORS; in isoal_rx_unframed_consume()
944 if (sp->fsm != ISOAL_ERR_SPOOL && (!pdu_padding || end_of_packet)) { in isoal_rx_unframed_consume()
949 bool append_as_padding = pdu_padding && !sp->only_padding; in isoal_rx_unframed_consume()
956 sp->fsm = next_state; in isoal_rx_unframed_consume()
957 sp->prev_pdu_id = meta->payload_number; in isoal_rx_unframed_consume()
958 sp->prev_pdu_is_end = !pdu_err && llid == PDU_BIS_LLID_COMPLETE_END; in isoal_rx_unframed_consume()
959 sp->prev_pdu_is_padding = !pdu_err && pdu_padding; in isoal_rx_unframed_consume()
961 sp->initialized = 1U; in isoal_rx_unframed_consume()
976 pdu_size_remaining >= PDU_ISO_SEG_HDR_SIZE + seg_hdr->len) { in isoal_check_seg_header()
993 * Time tracking is implemented based on using the incoming time-stamps of the
997 * BIS receiver, this reference is ahead of the time-stamp (anchorpoint),
1002 * This information is in-turn used to decided if SDUs are missing or lost and
1019 sp = &sink->sdu_production; in isoal_rx_framed_release_lost_sdus()
1020 session = &sink->session; in isoal_rx_framed_release_lost_sdus()
1021 sdu = &sp->sdu; in isoal_rx_framed_release_lost_sdus()
1025 if (isoal_get_time_diff(sdu->timestamp, next_sdu_timestamp, &time_elapsed)) { in isoal_rx_framed_release_lost_sdus()
1038 lost_sdus = (time_elapsed + (session->sdu_interval / 2)) / in isoal_rx_framed_release_lost_sdus()
1039 session->sdu_interval; in isoal_rx_framed_release_lost_sdus()
1051 lost_sdus = time_elapsed ? (time_elapsed / session->sdu_interval) + 1 : 0; in isoal_rx_framed_release_lost_sdus()
1057 sp->sdu_status |= ISOAL_SDU_STATUS_LOST_DATA; in isoal_rx_framed_release_lost_sdus()
1060 lost_sdus--; in isoal_rx_framed_release_lost_sdus()
1077 sp = &sink->sdu_production; in isoal_rx_framed_update_sdu_release()
1078 session = &sink->session; in isoal_rx_framed_update_sdu_release()
1079 sdu = &sp->sdu; in isoal_rx_framed_update_sdu_release()
1081 if (session->framed) { in isoal_rx_framed_update_sdu_release()
1083 timestamp = isoal_get_wrapped_time_us(sdu->timestamp, session->sdu_interval); in isoal_rx_framed_update_sdu_release()
1084 SET_RX_SDU_TIMESTAMP(sink, sdu->timestamp, timestamp); in isoal_rx_framed_update_sdu_release()
1118 sp = &sink->sdu_production; in isoal_rx_framed_consume()
1119 session = &sink->session; in isoal_rx_framed_consume()
1120 meta = pdu_meta->meta; in isoal_rx_framed_consume()
1121 sdu = &sp->sdu; in isoal_rx_framed_consume()
1123 iso_interval_us = session->iso_interval * ISO_INT_UNIT_US; in isoal_rx_framed_consume()
1127 pdu_err = (pdu_meta->meta->status != ISOAL_PDU_STATUS_VALID); in isoal_rx_framed_consume()
1128 pdu_padding = (pdu_meta->pdu->len == 0); in isoal_rx_framed_consume()
1130 if (sp->fsm == ISOAL_START) { in isoal_rx_framed_consume()
1133 seq_err = (meta->payload_number != (sp->prev_pdu_id + 1)); in isoal_rx_framed_consume()
1136 end_of_pdu = ((uint8_t *) pdu_meta->pdu->payload) + pdu_meta->pdu->len - 1UL; in isoal_rx_framed_consume()
1138 (struct pdu_iso_sdu_sh *) pdu_meta->pdu->payload; in isoal_rx_framed_consume()
1141 if (seg_hdr && isoal_check_seg_header(seg_hdr, pdu_meta->pdu->len) == in isoal_rx_framed_consume()
1148 timestamp = isoal_get_wrapped_time_us(meta->timestamp, in isoal_rx_framed_consume()
1149 session->sdu_sync_const - iso_interval_us); in isoal_rx_framed_consume()
1150 if (!sp->initialized) { in isoal_rx_framed_consume()
1153 SET_RX_SDU_TIMESTAMP(sink, sdu->timestamp, timestamp); in isoal_rx_framed_consume()
1164 const uint8_t sc = seg_hdr->sc; in isoal_rx_framed_consume()
1165 const uint8_t cmplt = seg_hdr->cmplt; in isoal_rx_framed_consume()
1167 if (sp->fsm == ISOAL_START) { in isoal_rx_framed_consume()
1168 sp->sdu_status = ISOAL_SDU_STATUS_VALID; in isoal_rx_framed_consume()
1169 sp->sdu_state = BT_ISO_START; in isoal_rx_framed_consume()
1172 ISOAL_LOG_DBGV("[%p] State %s", sink, FSM_TO_STR(sp->fsm)); in isoal_rx_framed_consume()
1173 switch (sp->fsm) { in isoal_rx_framed_consume()
1176 /* Start segment, included time-offset */ in isoal_rx_framed_consume()
1177 timeoffset = sys_le24_to_cpu(seg_hdr->timeoffset); in isoal_rx_framed_consume()
1178 anchorpoint = meta->timestamp; in isoal_rx_framed_consume()
1179 latency = session->sdu_sync_const; in isoal_rx_framed_consume()
1181 latency - timeoffset); in isoal_rx_framed_consume()
1186 SET_RX_SDU_TIMESTAMP(sink, sdu->timestamp, timestamp); in isoal_rx_framed_consume()
1233 /* Start segment, included time-offset */ in isoal_rx_framed_consume()
1234 timeoffset = sys_le24_to_cpu(seg_hdr->timeoffset); in isoal_rx_framed_consume()
1235 anchorpoint = meta->timestamp; in isoal_rx_framed_consume()
1236 latency = session->sdu_sync_const; in isoal_rx_framed_consume()
1238 latency - timeoffset); in isoal_rx_framed_consume()
1243 SET_RX_SDU_TIMESTAMP(sink, sdu->timestamp, timestamp); in isoal_rx_framed_consume()
1271 sp->sdu_status = ISOAL_SDU_STATUS_VALID; in isoal_rx_framed_consume()
1272 /* sp->sdu_state will be set by next_state decided above */ in isoal_rx_framed_consume()
1281 uint8_t offset = ((uint8_t *) seg_hdr) + PDU_ISO_SEG_HDR_SIZE - in isoal_rx_framed_consume()
1282 pdu_meta->pdu->payload; in isoal_rx_framed_consume()
1283 uint8_t length = seg_hdr->len; in isoal_rx_framed_consume()
1288 length = length - PDU_ISO_SEG_TIMEOFFSET_SIZE; in isoal_rx_framed_consume()
1300 sp->fsm = next_state; in isoal_rx_framed_consume()
1304 seg_hdr->len + PDU_ISO_SEG_HDR_SIZE); in isoal_rx_framed_consume()
1309 (uint8_t)(end_of_pdu + 1UL - ((uint8_t *) seg_hdr))) == in isoal_rx_framed_consume()
1342 next_sdu_status |= meta->status; in isoal_rx_framed_consume()
1345 switch (sp->fsm) { in isoal_rx_framed_consume()
1361 (pdu_err && meta->status == ISOAL_SDU_STATUS_ERRORS); in isoal_rx_framed_consume()
1366 sp->sdu_status = next_sdu_status; in isoal_rx_framed_consume()
1377 sp->sdu_status = next_sdu_status; in isoal_rx_framed_consume()
1391 sp->fsm = next_state; in isoal_rx_framed_consume()
1394 sp->prev_pdu_id = meta->payload_number; in isoal_rx_framed_consume()
1395 sp->initialized = 1U; in isoal_rx_framed_consume()
1414 if (sink && sink->sdu_production.mode != ISOAL_PRODUCTION_MODE_DISABLED) { in isoal_rx_pdu_recombine()
1415 if (sink->session.framed) { in isoal_rx_pdu_recombine()
1428 * @brief Find free source from statically-sized pool and allocate it
1466 pp = &source->pdu_production; in isoal_source_deallocate()
1468 if (pp->pdu_available > 0) { in isoal_source_deallocate()
1470 if (source && source->session.pdu_release) { in isoal_source_deallocate()
1471 source->session.pdu_release(pp->pdu.contents.handle, in isoal_source_deallocate()
1472 source->session.handle, in isoal_source_deallocate()
1551 session->handle = handle; in isoal_source_create()
1552 session->framed = framed; in isoal_source_create()
1553 session->bis = role == ISOAL_ROLE_BROADCAST_SOURCE; in isoal_source_create()
1554 session->burst_number = burst_number; in isoal_source_create()
1555 session->iso_interval = iso_interval; in isoal_source_create()
1556 session->sdu_interval = sdu_interval; in isoal_source_create()
1564 session->pdus_per_sdu = (burst_number * sdu_interval) / in isoal_source_create()
1567 session->max_pdu_size = max_octets; in isoal_source_create()
1569 /* Remember the platform-specific callbacks */ in isoal_source_create()
1570 session->pdu_alloc = pdu_alloc; in isoal_source_create()
1571 session->pdu_write = pdu_write; in isoal_source_create()
1572 session->pdu_emit = pdu_emit; in isoal_source_create()
1573 session->pdu_release = pdu_release; in isoal_source_create()
1578 session->sn = 0; in isoal_source_create()
1584 * @brief Atomically enable latch-in of packets and PDU production
1602 * @brief Atomically disable latch-in of packets and PDU production
1635 session = &source_ctx->session; in isoal_is_time_stamp_valid()
1643 * BT Core V5.4 : Vol 6 Low Energy Controller : Part G IS0-AL: in isoal_is_time_stamp_valid()
1651 const uint32_t sdu_interval_us = session->sdu_interval; in isoal_is_time_stamp_valid()
1652 const uint32_t iso_interval_us = session->iso_interval * ISO_INT_UNIT_US; in isoal_is_time_stamp_valid()
1658 (-time_stamp_valid_half_range)); in isoal_is_time_stamp_valid()
1672 * @param[in] source_ctx ISO-AL source reference for this CIS / BIS
1692 handle = bt_iso_handle(source_ctx->session.handle); in isoal_tx_pdu_emit()
1695 node_tx = produced_pdu->contents.handle; in isoal_tx_pdu_emit()
1702 node_tx->payload_count = payload_number & 0x7fffffffff; in isoal_tx_pdu_emit()
1703 node_tx->sdu_fragments = sdu_fragments; in isoal_tx_pdu_emit()
1705 produced_pdu->contents.pdu->ll_id = pdu_ll_id; in isoal_tx_pdu_emit()
1707 produced_pdu->contents.pdu->len = (uint8_t)payload_size; in isoal_tx_pdu_emit()
1710 status = source_ctx->session.pdu_emit(node_tx, handle); in isoal_tx_pdu_emit()
1714 produced_pdu->contents.pdu->len, sdu_fragments); in isoal_tx_pdu_emit()
1721 source_ctx->session.pdu_release(node_tx, handle, status); in isoal_tx_pdu_emit()
1729 * @param[in] source ISO-AL source reference
1744 session = &source->session; in isoal_tx_allocate_pdu()
1745 pp = &source->pdu_production; in isoal_tx_allocate_pdu()
1746 pdu = &pp->pdu; in isoal_tx_allocate_pdu()
1749 const bool pdu_complete = (pp->pdu_available == 0); in isoal_tx_allocate_pdu()
1753 err = session->pdu_alloc( in isoal_tx_allocate_pdu()
1754 &pdu->contents /* [out] Updated with pointer and size */ in isoal_tx_allocate_pdu()
1758 pdu->contents.handle = NULL; in isoal_tx_allocate_pdu()
1759 pdu->contents.pdu = NULL; in isoal_tx_allocate_pdu()
1760 pdu->contents.size = 0; in isoal_tx_allocate_pdu()
1765 session->max_pdu_size, in isoal_tx_allocate_pdu()
1766 pdu->contents.size in isoal_tx_allocate_pdu()
1770 pp->pdu_written = 0; in isoal_tx_allocate_pdu()
1771 pp->pdu_available = available_len; in isoal_tx_allocate_pdu()
1772 pp->pdu_allocated = 1U; in isoal_tx_allocate_pdu()
1775 pp->pdu_cnt++; in isoal_tx_allocate_pdu()
1783 * @param[in] source ISO-AL source reference
1797 pp = &source->pdu_production; in isoal_tx_try_emit_pdu()
1798 pdu = &pp->pdu; in isoal_tx_try_emit_pdu()
1801 const bool pdu_complete = (pp->pdu_available == 0) || force_emit; in isoal_tx_try_emit_pdu()
1804 pp->pdu_available = 0; in isoal_tx_try_emit_pdu()
1810 pp->sdu_fragments, in isoal_tx_try_emit_pdu()
1811 pp->payload_number, in isoal_tx_try_emit_pdu()
1812 pp->pdu_written); in isoal_tx_try_emit_pdu()
1813 pp->payload_number++; in isoal_tx_try_emit_pdu()
1814 pp->sdu_fragments = 0; in isoal_tx_try_emit_pdu()
1815 pp->pdu_allocated = 0U; in isoal_tx_try_emit_pdu()
1839 session = &source->session; in isoal_tx_unframed_get_next_payload_number()
1840 pp = &source->pdu_production; in isoal_tx_unframed_get_next_payload_number()
1845 *payload_number = pp->payload_number; in isoal_tx_unframed_get_next_payload_number()
1848 if (tx_sdu->sdu_state == BT_ISO_START || in isoal_tx_unframed_get_next_payload_number()
1849 tx_sdu->sdu_state == BT_ISO_SINGLE) { in isoal_tx_unframed_get_next_payload_number()
1859 if (IS_ENABLED(CONFIG_BT_CTLR_ISOAL_SN_STRICT) && pp->initialized) { in isoal_tx_unframed_get_next_payload_number()
1867 time_diff_valid = isoal_get_time_diff(session->last_input_time_stamp, in isoal_tx_unframed_get_next_payload_number()
1868 tx_sdu->time_stamp, in isoal_tx_unframed_get_next_payload_number()
1877 if (tx_sdu->packet_sn > session->last_input_sn + 1) { in isoal_tx_unframed_get_next_payload_number()
1882 sdus_skipped = (tx_sdu->packet_sn - session->last_input_sn) - 1; in isoal_tx_unframed_get_next_payload_number()
1883 *payload_number = pp->payload_number + in isoal_tx_unframed_get_next_payload_number()
1884 (sdus_skipped * session->pdus_per_sdu); in isoal_tx_unframed_get_next_payload_number()
1886 } else if (tx_sdu->packet_sn == session->last_input_sn && in isoal_tx_unframed_get_next_payload_number()
1887 time_diff_valid && time_diff > session->sdu_interval) { in isoal_tx_unframed_get_next_payload_number()
1893 /* Round at mid-point */ in isoal_tx_unframed_get_next_payload_number()
1894 sdus_skipped = ((time_diff + (session->sdu_interval / 2)) / in isoal_tx_unframed_get_next_payload_number()
1895 session->sdu_interval) - 1; in isoal_tx_unframed_get_next_payload_number()
1896 *payload_number = pp->payload_number + in isoal_tx_unframed_get_next_payload_number()
1897 (sdus_skipped * session->pdus_per_sdu); in isoal_tx_unframed_get_next_payload_number()
1906 *payload_number = MAX(pp->payload_number, in isoal_tx_unframed_get_next_payload_number()
1907 (tx_sdu->target_event * session->burst_number)); in isoal_tx_unframed_get_next_payload_number()
1930 * receiver for each SDU and there were problems with LL/CIS/PER/BV-39-C which
1944 * the ISO-AL with a notion of time, for example when storing information
1978 session = &source->session; in isoal_tx_unframed_produce()
1979 pp = &source->pdu_production; in isoal_tx_unframed_produce()
1983 packet_available = tx_sdu->size; in isoal_tx_unframed_produce()
1984 sdu_payload = tx_sdu->dbuf; in isoal_tx_unframed_produce()
1988 tx_sdu->sdu_state == BT_ISO_SINGLE); in isoal_tx_unframed_produce()
1990 if (tx_sdu->sdu_state == BT_ISO_START || in isoal_tx_unframed_produce()
1991 tx_sdu->sdu_state == BT_ISO_SINGLE) { in isoal_tx_unframed_produce()
2000 actual_grp_ref_point = tx_sdu->grp_ref_point; in isoal_tx_unframed_produce()
2005 time_diff_valid = isoal_get_time_diff(session->last_input_time_stamp, in isoal_tx_unframed_produce()
2006 tx_sdu->time_stamp, in isoal_tx_unframed_produce()
2011 pp->payload_number = next_payload_number; in isoal_tx_unframed_produce()
2015 * BT Core V5.3 : Vol 6 Low Energy Controller : Part G IS0-AL: in isoal_tx_unframed_produce()
2025 session->sn += sdus_skipped + 1; in isoal_tx_unframed_produce()
2028 actual_event = pp->payload_number / session->burst_number; in isoal_tx_unframed_produce()
2036 if (actual_event != tx_sdu->target_event) { in isoal_tx_unframed_produce()
2038 isoal_get_wrapped_time_us(tx_sdu->grp_ref_point, in isoal_tx_unframed_produce()
2039 (actual_event - tx_sdu->target_event) * in isoal_tx_unframed_produce()
2040 session->iso_interval * ISO_INT_UNIT_US); in isoal_tx_unframed_produce()
2044 session->tx_time_stamp = actual_grp_ref_point; in isoal_tx_unframed_produce()
2045 /* BT Core V5.3 : Vol 4 HCI : Part E HCI Functional Spec: in isoal_tx_unframed_produce()
2054 pp->pdu_cnt = 0; in isoal_tx_unframed_produce()
2059 pp->sdu_fragments = 0; in isoal_tx_unframed_produce()
2062 session->last_input_sn = tx_sdu->packet_sn; in isoal_tx_unframed_produce()
2064 if (!time_diff_valid || time_diff < session->sdu_interval) { in isoal_tx_unframed_produce()
2065 /* If the time-stamp is invalid or the difference is in isoal_tx_unframed_produce()
2072 session->last_input_time_stamp = isoal_get_wrapped_time_us( in isoal_tx_unframed_produce()
2073 session->last_input_time_stamp, in isoal_tx_unframed_produce()
2074 session->sdu_interval); in isoal_tx_unframed_produce()
2076 session->last_input_time_stamp = tx_sdu->time_stamp; in isoal_tx_unframed_produce()
2087 struct isoal_pdu_produced *pdu = &pp->pdu; in isoal_tx_unframed_produce()
2092 * - What can fit in the destination PDU. in isoal_tx_unframed_produce()
2093 * - What remains of the packet. in isoal_tx_unframed_produce()
2097 pp->pdu_available in isoal_tx_unframed_produce()
2108 err |= session->pdu_write(&pdu->contents, in isoal_tx_unframed_produce()
2109 pp->pdu_written, in isoal_tx_unframed_produce()
2113 pp->pdu_written += consume_len; in isoal_tx_unframed_produce()
2114 pp->pdu_available -= consume_len; in isoal_tx_unframed_produce()
2115 packet_available -= consume_len; in isoal_tx_unframed_produce()
2122 pp->sdu_fragments++; in isoal_tx_unframed_produce()
2129 ((tx_sdu->sdu_state == BT_ISO_SINGLE) || in isoal_tx_unframed_produce()
2130 (tx_sdu->sdu_state == BT_ISO_END)); in isoal_tx_unframed_produce()
2134 * BT Core V5.3 : Vol 6 Low Energy Controller : Part G IS0-AL: in isoal_tx_unframed_produce()
2161 * BT Core V5.3 : Vol 6 Low Energy Controller : Part G IS0-AL: in isoal_tx_unframed_produce()
2168 padding_pdu = (end_of_sdu && (pp->pdu_cnt < session->pdus_per_sdu)); in isoal_tx_unframed_produce()
2172 pp->initialized = 1U; in isoal_tx_unframed_produce()
2198 session = &source->session; in isoal_insert_seg_header_timeoffset()
2199 pp = &source->pdu_production; in isoal_insert_seg_header_timeoffset()
2200 pdu = &pp->pdu; in isoal_insert_seg_header_timeoffset()
2209 if (pp->pdu_available < write_size) { in isoal_insert_seg_header_timeoffset()
2223 pp->seg_hdr_sc = seg_hdr.sc; in isoal_insert_seg_header_timeoffset()
2224 pp->seg_hdr_length = seg_hdr.len; in isoal_insert_seg_header_timeoffset()
2229 pp->last_seg_hdr_loc = pp->pdu_written; in isoal_insert_seg_header_timeoffset()
2231 err = session->pdu_write(&pdu->contents, in isoal_insert_seg_header_timeoffset()
2232 pp->pdu_written, in isoal_insert_seg_header_timeoffset()
2235 pp->pdu_written += write_size; in isoal_insert_seg_header_timeoffset()
2236 pp->pdu_available -= write_size; in isoal_insert_seg_header_timeoffset()
2260 session = &source->session; in isoal_update_seg_header_cmplt_length()
2261 pp = &source->pdu_production; in isoal_update_seg_header_cmplt_length()
2262 pdu = &pp->pdu; in isoal_update_seg_header_cmplt_length()
2265 seg_hdr.sc = pp->seg_hdr_sc; in isoal_update_seg_header_cmplt_length()
2269 pp->seg_hdr_length += add_length; in isoal_update_seg_header_cmplt_length()
2270 seg_hdr.len = pp->seg_hdr_length; in isoal_update_seg_header_cmplt_length()
2273 /* Re-write the segmentation header at the same location */ in isoal_update_seg_header_cmplt_length()
2274 return session->pdu_write(&pdu->contents, in isoal_update_seg_header_cmplt_length()
2275 pp->last_seg_hdr_loc, in isoal_update_seg_header_cmplt_length()
2310 session = &source_ctx->session; in isoal_tx_framed_find_correct_tx_event()
2311 pp = &source_ctx->pdu_production; in isoal_tx_framed_find_correct_tx_event()
2317 next_payload_number = pp->payload_number; in isoal_tx_framed_find_correct_tx_event()
2318 actual_event = pp->payload_number / session->burst_number; in isoal_tx_framed_find_correct_tx_event()
2329 if (actual_event != tx_sdu->target_event) { in isoal_tx_framed_find_correct_tx_event()
2330 actual_grp_ref_point = isoal_get_wrapped_time_us(tx_sdu->grp_ref_point, in isoal_tx_framed_find_correct_tx_event()
2331 ((actual_event - tx_sdu->target_event) * session->iso_interval * in isoal_tx_framed_find_correct_tx_event()
2334 actual_grp_ref_point = tx_sdu->grp_ref_point; in isoal_tx_framed_find_correct_tx_event()
2340 if (tx_sdu->sdu_state == BT_ISO_START || in isoal_tx_framed_find_correct_tx_event()
2341 tx_sdu->sdu_state == BT_ISO_SINGLE) { in isoal_tx_framed_find_correct_tx_event()
2345 tx_sdu->cntr_time_stamp, in isoal_tx_framed_find_correct_tx_event()
2346 tx_sdu->time_stamp); in isoal_tx_framed_find_correct_tx_event()
2347 const uint16_t offset_margin = session->bis ? in isoal_tx_framed_find_correct_tx_event()
2352 if (pp->initialized) { in isoal_tx_framed_find_correct_tx_event()
2357 time_diff_valid = isoal_get_time_diff(session->last_input_time_stamp, in isoal_tx_framed_find_correct_tx_event()
2358 tx_sdu->time_stamp, in isoal_tx_framed_find_correct_tx_event()
2362 if (tx_sdu->packet_sn > session->last_input_sn + 1) { in isoal_tx_framed_find_correct_tx_event()
2364 sdus_skipped = (tx_sdu->packet_sn - session->last_input_sn) - 1; in isoal_tx_framed_find_correct_tx_event()
2366 } else if (tx_sdu->packet_sn == session->last_input_sn && in isoal_tx_framed_find_correct_tx_event()
2367 time_diff_valid && time_diff > session->sdu_interval) { in isoal_tx_framed_find_correct_tx_event()
2370 /* Round at mid-point */ in isoal_tx_framed_find_correct_tx_event()
2371 sdus_skipped = ((time_diff + (session->sdu_interval / 2)) / in isoal_tx_framed_find_correct_tx_event()
2372 session->sdu_interval) - 1; in isoal_tx_framed_find_correct_tx_event()
2381 time_stamp_selected = tx_sdu->time_stamp; in isoal_tx_framed_find_correct_tx_event()
2389 session->tx_time_stamp, in isoal_tx_framed_find_correct_tx_event()
2390 time_diff - session->tx_time_offset); in isoal_tx_framed_find_correct_tx_event()
2398 session->tx_time_stamp, in isoal_tx_framed_find_correct_tx_event()
2399 ((sdus_skipped + 1) * session->sdu_interval) in isoal_tx_framed_find_correct_tx_event()
2400 - session->tx_time_offset); in isoal_tx_framed_find_correct_tx_event()
2407 if (actual_event < tx_sdu->target_event) { in isoal_tx_framed_find_correct_tx_event()
2408 actual_event = tx_sdu->target_event; in isoal_tx_framed_find_correct_tx_event()
2409 actual_grp_ref_point = tx_sdu->grp_ref_point; in isoal_tx_framed_find_correct_tx_event()
2415 /* Time stamp is within valid range - in isoal_tx_framed_find_correct_tx_event()
2418 time_stamp_selected = tx_sdu->time_stamp; in isoal_tx_framed_find_correct_tx_event()
2422 /* Time stamp is out of range - in isoal_tx_framed_find_correct_tx_event()
2425 time_stamp_selected = tx_sdu->cntr_time_stamp; in isoal_tx_framed_find_correct_tx_event()
2439 * BT Core V5.3 : Vol 6 Low Energy Controller : Part G IS0-AL: in isoal_tx_framed_find_correct_tx_event()
2448 session->iso_interval * ISO_INT_UNIT_US); in isoal_tx_framed_find_correct_tx_event()
2452 source_ctx, (actual_event * session->burst_number), actual_event, in isoal_tx_framed_find_correct_tx_event()
2460 next_payload_number = MAX(pp->payload_number, in isoal_tx_framed_find_correct_tx_event()
2461 (actual_event * session->burst_number)); in isoal_tx_framed_find_correct_tx_event()
2464 source, actual_event, (actual_event * session->burst_number), in isoal_tx_framed_find_correct_tx_event()
2474 * time-offset of 24-bits. in isoal_tx_framed_find_correct_tx_event()
2509 session = &source->session; in isoal_tx_framed_produce()
2510 pp = &source->pdu_production; in isoal_tx_framed_produce()
2515 packet_available = tx_sdu->size; in isoal_tx_framed_produce()
2516 sdu_payload = tx_sdu->dbuf; in isoal_tx_framed_produce()
2520 tx_sdu->sdu_state == BT_ISO_SINGLE); in isoal_tx_framed_produce()
2523 source, tx_sdu->packet_sn, tx_sdu->iso_sdu_length, tx_sdu->time_stamp, in isoal_tx_framed_produce()
2524 tx_sdu->grp_ref_point, tx_sdu->target_event, tx_sdu->sdu_state); in isoal_tx_framed_produce()
2526 if (tx_sdu->sdu_state == BT_ISO_START || in isoal_tx_framed_produce()
2527 tx_sdu->sdu_state == BT_ISO_SINGLE) { in isoal_tx_framed_produce()
2535 time_diff_valid = isoal_get_time_diff(session->last_input_time_stamp, in isoal_tx_framed_produce()
2536 tx_sdu->time_stamp, in isoal_tx_framed_produce()
2546 ISOAL_LOG_DBGV("[%p] Starting SDU %u PL=(%llu->%llu) Grp Ref=%lu TO=%lu", in isoal_tx_framed_produce()
2547 source, tx_sdu->packet_sn, pp->payload_number, next_payload_number, in isoal_tx_framed_produce()
2551 if (next_payload_number > pp->payload_number) { in isoal_tx_framed_produce()
2553 if (pp->pdu_allocated) { in isoal_tx_framed_produce()
2561 while (err == ISOAL_STATUS_OK && next_payload_number > pp->payload_number && in isoal_tx_framed_produce()
2562 (pp->payload_number % session->burst_number)) { in isoal_tx_framed_produce()
2570 pp->pdu_state = BT_ISO_START; in isoal_tx_framed_produce()
2573 pp->payload_number = next_payload_number; in isoal_tx_framed_produce()
2577 * BT Core V5.3 : Vol 6 Low Energy Controller : Part G IS0-AL: in isoal_tx_framed_produce()
2588 session->sn += sdus_skipped + 1; in isoal_tx_framed_produce()
2591 session->tx_time_stamp = actual_grp_ref_point; in isoal_tx_framed_produce()
2592 session->tx_time_offset = time_offset; in isoal_tx_framed_produce()
2595 pp->pdu_cnt = 0; in isoal_tx_framed_produce()
2598 session->last_input_sn = tx_sdu->packet_sn; in isoal_tx_framed_produce()
2600 if (pp->initialized && tx_sdu->time_stamp == tx_sdu->cntr_time_stamp && in isoal_tx_framed_produce()
2601 (!time_diff_valid || time_diff < session->sdu_interval)) { in isoal_tx_framed_produce()
2602 /* If the time-stamp is invalid or the difference is in isoal_tx_framed_produce()
2609 session->last_input_time_stamp = isoal_get_wrapped_time_us( in isoal_tx_framed_produce()
2610 session->last_input_time_stamp, in isoal_tx_framed_produce()
2611 session->sdu_interval); in isoal_tx_framed_produce()
2613 session->last_input_time_stamp = tx_sdu->time_stamp; in isoal_tx_framed_produce()
2624 struct isoal_pdu_produced *pdu = &pp->pdu; in isoal_tx_framed_produce()
2628 ISOAL_LOG_DBGV("[%p] State %s", source, STATE_TO_STR(pp->pdu_state)); in isoal_tx_framed_produce()
2629 if (pp->pdu_state == BT_ISO_START) { in isoal_tx_framed_produce()
2630 /* Start of a new SDU. Segmentation header and time-offset in isoal_tx_framed_produce()
2636 pp->pdu_state = BT_ISO_CONT; in isoal_tx_framed_produce()
2637 } else if (!padding_pdu && pp->pdu_state == BT_ISO_CONT && pp->pdu_written == 0) { in isoal_tx_framed_produce()
2648 * - What can fit in the destination PDU. in isoal_tx_framed_produce()
2649 * - What remains of the packet. in isoal_tx_framed_produce()
2653 pp->pdu_available in isoal_tx_framed_produce()
2664 err |= session->pdu_write(&pdu->contents, in isoal_tx_framed_produce()
2665 pp->pdu_written, in isoal_tx_framed_produce()
2669 pp->pdu_written += consume_len; in isoal_tx_framed_produce()
2670 pp->pdu_available -= consume_len; in isoal_tx_framed_produce()
2671 packet_available -= consume_len; in isoal_tx_framed_produce()
2678 pp->sdu_fragments++; in isoal_tx_framed_produce()
2685 ((tx_sdu->sdu_state == BT_ISO_SINGLE) || in isoal_tx_framed_produce()
2686 (tx_sdu->sdu_state == BT_ISO_END)); in isoal_tx_framed_produce()
2694 bool release_pdu = end_of_sdu && (pp->pdu_available <= ISOAL_TX_SEGMENT_MIN_SIZE); in isoal_tx_framed_produce()
2700 /* BT Core V5.3 : Vol 6 Low Energy Controller : Part G IS0-AL: in isoal_tx_framed_produce()
2714 pp->initialized = 1U; in isoal_tx_framed_produce()
2743 session = &source->session; in isoal_tx_framed_event_prepare_handle()
2744 pp = &source->pdu_production; in isoal_tx_framed_event_prepare_handle()
2745 first_event_payload = (session->burst_number * event_count); in isoal_tx_framed_event_prepare_handle()
2746 last_event_payload = (session->burst_number * (event_count + 1ULL)) - 1ULL; in isoal_tx_framed_event_prepare_handle()
2748 if (pp->pdu_allocated && pp->payload_number <= last_event_payload) { in isoal_tx_framed_event_prepare_handle()
2754 if (pp->mode != ISOAL_PRODUCTION_MODE_DISABLED) { in isoal_tx_framed_event_prepare_handle()
2756 * Part G IS0-AL: in isoal_tx_framed_event_prepare_handle()
2779 if (pp->payload_number > first_event_payload) { in isoal_tx_framed_event_prepare_handle()
2785 while (!err && !err_alloc && (pp->payload_number < last_event_payload + 1ULL)) { in isoal_tx_framed_event_prepare_handle()
2796 if (pp->payload_number < last_event_payload + 1ULL) { in isoal_tx_framed_event_prepare_handle()
2797 pp->payload_number = last_event_payload + 1ULL; in isoal_tx_framed_event_prepare_handle()
2798 ISOAL_LOG_DBGV("[%p] Prepare PL updated to %lu.", source, pp->payload_number); in isoal_tx_framed_event_prepare_handle()
2820 session = &source->session; in isoal_tx_sdu_fragment()
2826 source->context_active = 1U; in isoal_tx_sdu_fragment()
2828 if (source->pdu_production.mode != ISOAL_PRODUCTION_MODE_DISABLED) { in isoal_tx_sdu_fragment()
2829 /* BT Core V5.3 : Vol 6 Low Energy Controller : Part G IS0-AL: in isoal_tx_sdu_fragment()
2839 if (source->session.framed) { in isoal_tx_sdu_fragment()
2846 source->context_active = 0U; in isoal_tx_sdu_fragment()
2848 if (source->timeout_trigger) { in isoal_tx_sdu_fragment()
2849 source->timeout_trigger = 0U; in isoal_tx_sdu_fragment()
2850 if (session->framed) { in isoal_tx_sdu_fragment()
2853 source->timeout_event_count); in isoal_tx_sdu_fragment()
2865 if (source && source->session.pdu_release) { in isoal_tx_pdu_release()
2866 source->session.pdu_release(node_tx, source->session.handle, in isoal_tx_pdu_release()
2876 * @param offset Time-offset (Framed) / 0 (Unframed) of last SDU
2889 /* BT Core V5.3 : Vol 4 HCI : Part E HCI Functional Spec: in isoal_tx_get_sync_info()
2895 if (session->sn > 0) { in isoal_tx_get_sync_info()
2896 *seq = session->sn; in isoal_tx_get_sync_info()
2897 *timestamp = session->tx_time_stamp; in isoal_tx_get_sync_info()
2898 *offset = session->tx_time_offset; in isoal_tx_get_sync_info()
2920 session = &source->session; in isoal_tx_event_prepare()
2925 source->timeout_event_count = event_count; in isoal_tx_event_prepare()
2926 source->timeout_trigger = 1U; in isoal_tx_event_prepare()
2927 if (source->context_active) { in isoal_tx_event_prepare()
2930 source->timeout_trigger = 0U; in isoal_tx_event_prepare()
2932 if (session->framed) { in isoal_tx_event_prepare()