4646#endif /* CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_CONN_ISO */
4747} isoal_global ;
4848
49-
5049/**
5150 * @brief Internal reset
5251 * Zero-init entire ISO-AL state
@@ -110,6 +109,7 @@ static isoal_status_t isoal_sink_allocate(isoal_sink_handle_t *hdl)
110109static void isoal_sink_deallocate (isoal_sink_handle_t hdl )
111110{
112111 isoal_global .sink_allocated [hdl ] = ISOAL_ALLOC_STATE_FREE ;
112+ (void )memset (& isoal_global .sink_state [hdl ], 0 , sizeof (struct isoal_sink ));
113113}
114114
115115/**
@@ -122,8 +122,8 @@ static void isoal_sink_deallocate(isoal_sink_handle_t hdl)
122122 * @param flush_timeout[in] Flush timeout
123123 * @param sdu_interval[in] SDU interval
124124 * @param iso_interval[in] ISO interval
125- * @param stream_sync_delay[in] CIS sync delay
126- * @param group_sync_delay[in] CIG sync delay
125+ * @param stream_sync_delay[in] CIS / BIS sync delay
126+ * @param group_sync_delay[in] CIG / BIG sync delay
127127 * @param sdu_alloc[in] Callback of SDU allocator
128128 * @param sdu_emit[in] Callback of SDU emitter
129129 * @param sdu_write[in] Callback of SDU byte writer
@@ -987,6 +987,24 @@ static isoal_status_t isoal_source_allocate(isoal_source_handle_t *hdl)
987987static void isoal_source_deallocate (isoal_source_handle_t hdl )
988988{
989989 isoal_global .source_allocated [hdl ] = ISOAL_ALLOC_STATE_FREE ;
990+ (void )memset (& isoal_global .source_state [hdl ], 0 , sizeof (struct isoal_source ));
991+ }
992+
993+ /**
994+ * @brief Check if a provided handle is valid
995+ * @param[in] hdl Input handle for validation
996+ * @return Handle valid / not valid
997+ */
998+ static isoal_status_t isoal_check_source_hdl_valid (isoal_source_handle_t hdl )
999+ {
1000+ if (hdl < CONFIG_BT_CTLR_ISOAL_SOURCES &&
1001+ isoal_global .source_allocated [hdl ] == ISOAL_ALLOC_STATE_TAKEN ) {
1002+ return ISOAL_STATUS_OK ;
1003+ }
1004+
1005+ BT_ERR ("Invalid source handle (0x%02x)" , hdl );
1006+
1007+ return ISOAL_STATUS_ERR_UNSPECIFIED ;
9901008}
9911009
9921010/**
@@ -1000,8 +1018,8 @@ static void isoal_source_deallocate(isoal_source_handle_t hdl)
10001018 * @param max_octets[in] Maximum PDU size (Max_PDU_C_To_P / Max_PDU_P_To_C)
10011019 * @param sdu_interval[in] SDU interval
10021020 * @param iso_interval[in] ISO interval
1003- * @param stream_sync_delay[in] CIS sync delay
1004- * @param group_sync_delay[in] CIG sync delay
1021+ * @param stream_sync_delay[in] CIS / BIS sync delay
1022+ * @param group_sync_delay[in] CIG / BIG sync delay
10051023 * @param pdu_alloc[in] Callback of PDU allocator
10061024 * @param pdu_write[in] Callback of PDU byte writer
10071025 * @param pdu_emit[in] Callback of PDU emitter
@@ -1293,6 +1311,10 @@ static isoal_status_t isoal_tx_unframed_produce(struct isoal_source *source,
12931311
12941312 if (tx_sdu -> sdu_state == BT_ISO_START ||
12951313 tx_sdu -> sdu_state == BT_ISO_SINGLE ) {
1314+ /* Initialize to info provided in SDU */
1315+ uint32_t actual_grp_ref_point = tx_sdu -> grp_ref_point ;
1316+ uint64_t actual_event = tx_sdu -> target_event ;
1317+
12961318 /* Start of a new SDU */
12971319
12981320 /* Update sequence number for received SDU
@@ -1320,6 +1342,33 @@ static isoal_status_t isoal_tx_unframed_produce(struct isoal_source *source,
13201342 pp -> payload_number = MAX (pp -> payload_number ,
13211343 (tx_sdu -> target_event * session -> burst_number ));
13221344
1345+ /* Get actual event for this payload number */
1346+ actual_event = pp -> payload_number / session -> burst_number ;
1347+
1348+ /* Get group reference point for this PDU based on the actual
1349+ * event being set. This might introduce some errors as the
1350+ * group refernce point for future events could drift. However
1351+ * as the time offset calculation requires an absolute value,
1352+ * this seems to be the best candidate. As the actual group
1353+ * refereence point is 32-bits, it is expected that advancing
1354+ * the reference point will cause it to wrap around.
1355+ */
1356+ if (actual_event > tx_sdu -> target_event ) {
1357+ actual_grp_ref_point = (uint32_t )(tx_sdu -> grp_ref_point +
1358+ ((actual_event - tx_sdu -> target_event ) * session -> iso_interval *
1359+ ISO_INT_UNIT_US ));
1360+ }
1361+
1362+ /* Store timing info for TX Sync command */
1363+ session -> tx_time_stamp = actual_grp_ref_point ;
1364+ /* BT Core V5.3 : Vol 4 HCI : Part E HCI Functional Spec:
1365+ * 7.8.96 LE Read ISO TX Sync Command:
1366+ * When the Connection_Handle identifies a CIS or BIS that is
1367+ * transmitting unframed PDUs the value of Time_Offset returned
1368+ * shall be zero
1369+ * Relies on initialization value being 0.
1370+ */
1371+
13231372 /* Reset PDU fragmentation count for this SDU */
13241373 pp -> pdu_cnt = 0 ;
13251374
@@ -1564,7 +1613,7 @@ static isoal_status_t isoal_tx_framed_produce(struct isoal_source *source,
15641613 /* Start of a new SDU */
15651614
15661615 /* Initialize to info provided in SDU */
1567- uint32_t actual_cig_ref_point = tx_sdu -> cig_ref_point ;
1616+ uint32_t actual_grp_ref_point = tx_sdu -> grp_ref_point ;
15681617 uint64_t actual_event = tx_sdu -> target_event ;
15691618
15701619 /* Update sequence number for received SDU
@@ -1598,38 +1647,43 @@ static isoal_status_t isoal_tx_framed_produce(struct isoal_source *source,
15981647 /* Get actual event for this payload number */
15991648 actual_event = pp -> payload_number / session -> burst_number ;
16001649
1601- /* Get cig reference point for this PDU based on the actual
1602- * event being set. This might introduce some errors as the cig
1603- * refernce point for future events could drift. However as the
1604- * time offset calculation requires an absolute value, this
1605- * seems to be the best candidate.
1650+ /* Get group reference point for this PDU based on the actual
1651+ * event being set. This might introduce some errors as the
1652+ * group refernce point for future events could drift. However
1653+ * as the time offset calculation requires an absolute value,
1654+ * this seems to be the best candidate.
16061655 */
16071656 if (actual_event > tx_sdu -> target_event ) {
1608- actual_cig_ref_point = tx_sdu -> cig_ref_point +
1657+ actual_grp_ref_point = tx_sdu -> grp_ref_point +
16091658 ((actual_event - tx_sdu -> target_event ) * session -> iso_interval *
16101659 ISO_INT_UNIT_US );
16111660 }
16121661
1613- /* Check if time stamp on packet is later than the CIG reference
1614- * point and adjust targets. This could happen if the SDU has
1615- * been time-stampped at the controller when received via HCI.
1662+ /* Check if time stamp on packet is later than the group
1663+ * reference point and adjust targets. This could happen if the
1664+ * SDU has been time-stampped at the controller when received
1665+ * via HCI.
16161666 *
16171667 * BT Core V5.3 : Vol 6 Low Energy Controller : Part G IS0-AL:
16181668 * 3.1 Time_Offset in framed PDUs :
16191669 * The Time_Offset shall be a positive value.
16201670 */
1621- if (actual_cig_ref_point <= tx_sdu -> time_stamp ) {
1671+ if (actual_grp_ref_point <= tx_sdu -> time_stamp ) {
16221672 /* Advance target to next event */
16231673 actual_event ++ ;
1624- actual_cig_ref_point += session -> iso_interval * ISO_INT_UNIT_US ;
1674+ actual_grp_ref_point += session -> iso_interval * ISO_INT_UNIT_US ;
16251675
16261676 /* Set payload number */
16271677 pp -> payload_number = actual_event * session -> burst_number ;
16281678 }
16291679
16301680 /* Calculate the time offset */
1631- LL_ASSERT (actual_cig_ref_point > tx_sdu -> time_stamp );
1632- time_offset = actual_cig_ref_point - tx_sdu -> time_stamp ;
1681+ LL_ASSERT (actual_grp_ref_point > tx_sdu -> time_stamp );
1682+ time_offset = actual_grp_ref_point - tx_sdu -> time_stamp ;
1683+
1684+ /* Store timing info for TX Sync command */
1685+ session -> tx_time_stamp = actual_grp_ref_point ;
1686+ session -> tx_time_offset = time_offset ;
16331687
16341688 /* Reset PDU fragmentation count for this SDU */
16351689 pp -> pdu_cnt = 0 ;
@@ -1793,4 +1847,40 @@ void isoal_tx_pdu_release(isoal_source_handle_t source_hdl,
17931847 ISOAL_STATUS_OK );
17941848 }
17951849}
1850+
1851+ /**
1852+ * @brief Get information required for HCI_LE_Read_ISO_TX_Sync
1853+ * @param source_hdl Source handle linked to handle provided in HCI message
1854+ * @param seq Packet Sequence number of last SDU
1855+ * @param timestamp CIG / BIG reference point of last SDU
1856+ * @param offset Time-offset (Framed) / 0 (Unframed) of last SDU
1857+ * @return Operation status
1858+ */
1859+ isoal_status_t isoal_tx_get_sync_info (isoal_source_handle_t source_hdl ,
1860+ uint16_t * seq ,
1861+ uint32_t * timestamp ,
1862+ uint32_t * offset )
1863+ {
1864+ if (isoal_check_source_hdl_valid (source_hdl ) == ISOAL_STATUS_OK ) {
1865+ struct isoal_source_session * session ;
1866+
1867+ session = & isoal_global .source_state [source_hdl ].session ;
1868+
1869+ /* BT Core V5.3 : Vol 4 HCI : Part E HCI Functional Spec:
1870+ * 7.8.96 LE Read ISO TX Sync Command:
1871+ * If the Host issues this command before an SDU had been transmitted by
1872+ * the Controller, then Controller shall return the error code Command
1873+ * Disallowed.
1874+ */
1875+ if (session -> seqn > 0 ) {
1876+ * seq = session -> seqn ;
1877+ * timestamp = session -> tx_time_stamp ;
1878+ * offset = session -> tx_time_offset ;
1879+ return ISOAL_STATUS_OK ;
1880+ }
1881+ }
1882+
1883+ return ISOAL_STATUS_ERR_UNSPECIFIED ;
1884+ }
1885+
17961886#endif /* CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_CONN_ISO */
0 commit comments