@@ -52,8 +52,20 @@ struct bt_le_audio_tx_info {
5252static bool initialized ;
5353static struct bt_le_audio_tx_info tx_info [SRC_STREAM_COUNT ];
5454
55+ /**
56+ * @brief Sends audio data over a single BAP stream.
57+ *
58+ * @param data Audio data to send.
59+ * @param size Size of data.
60+ * @param bap_stream Pointer to BAP stream to use.
61+ * @param tx_info Pointer to tx_info struct.
62+ * @param ts_tx Timestamp to send. Note that for some controllers, BT_ISO_TIMESTAMP_NONE
63+ * is used. This timestamp is used to ensure that SDUs are sent in the same
64+ * connection interval.
65+ * @return 0 if successful, error otherwise.
66+ */
5567static int iso_stream_send (uint8_t const * const data , size_t size , struct bt_bap_stream * bap_stream ,
56- struct bt_le_audio_tx_info * tx_info )
68+ struct bt_le_audio_tx_info * tx_info , uint32_t ts_tx )
5769{
5870 int ret ;
5971 struct net_buf * buf ;
@@ -93,9 +105,15 @@ static int iso_stream_send(uint8_t const *const data, size_t size, struct bt_bap
93105
94106 atomic_inc (& tx_info -> iso_tx_pool_alloc );
95107
96- ret = bt_bap_stream_send (bap_stream , buf , tx_info -> iso_tx .seq_num , BT_ISO_TIMESTAMP_NONE );
108+ if (IS_ENABLED (CONFIG_BT_LL_ACS_NRF53 )) {
109+ ret = bt_bap_stream_send (bap_stream , buf , tx_info -> iso_tx .seq_num ,
110+ BT_ISO_TIMESTAMP_NONE );
111+ } else {
112+ ret = bt_bap_stream_send (bap_stream , buf , tx_info -> iso_tx .seq_num , ts_tx );
113+ }
114+
97115 if (ret < 0 ) {
98- LOG_WRN ("Failed to send audio data: %d" , ret );
116+ LOG_WRN ("Failed to send audio data: %d stream %p " , ret , bap_stream );
99117 net_buf_unref (buf );
100118 atomic_dec (& tx_info -> iso_tx_pool_alloc );
101119 } else {
@@ -109,9 +127,6 @@ int bt_le_audio_tx_send(struct bt_bap_stream **bap_streams, struct le_audio_enco
109127 uint8_t streams_to_tx )
110128{
111129 int ret ;
112- uint32_t ts = 0 ;
113- bool any_chan_streaming = false;
114- bool got_tx_sync_ts = false;
115130 size_t data_size_pr_stream = 0 ;
116131
117132 if (!initialized ) {
@@ -143,40 +158,64 @@ int bt_le_audio_tx_send(struct bt_bap_stream **bap_streams, struct le_audio_enco
143158 return - EINVAL ;
144159 }
145160
161+ /* When sending data, we always send ts = 0 to the first active transmitting channel.
162+ * The controller will populate with a ts which is fetched using bt_iso_chan_get_tx_sync.
163+ * This timestamp will be submitted to all the other channels in order to place data on all
164+ * channels in the same ISO interval.
165+ */
166+
167+ uint32_t ts_common = 0 ;
168+ bool ts_common_acquired = false;
169+ uint32_t common_interval = 0 ;
170+
146171 for (int i = 0 ; i < streams_to_tx ; i ++ ) {
147- if (le_audio_ep_state_check (bap_streams [i ]-> ep , BT_BAP_EP_STATE_STREAMING )) {
148- any_chan_streaming = true;
149-
150- if (!got_tx_sync_ts ) {
151- struct bt_iso_chan * iso_chan ;
152-
153- iso_chan = bt_bap_stream_iso_chan_get (bap_streams [i ]);
154- if (iso_chan == NULL ) {
155- LOG_ERR ("Unable to get iso chan" );
156- continue ;
157- }
158-
159- ret = bt_iso_chan_get_tx_sync (iso_chan , & tx_info [i ].iso_tx );
160- if (ret ) {
161- continue ;
162- }
163- ts = tx_info [i ].iso_tx .ts ;
164- got_tx_sync_ts = true;
165- }
172+ if (!le_audio_ep_state_check (bap_streams [i ]-> ep , BT_BAP_EP_STATE_STREAMING )) {
173+ /* This bap_stream is not streaming*/
174+ continue ;
166175 }
167- }
168176
169- if (!any_chan_streaming ) {
170- LOG_DBG ("No headset in stream state" );
171- return - ECANCELED ;
177+ if (common_interval != 0 && (common_interval != bap_streams [i ]-> qos -> interval )) {
178+ LOG_ERR ("Not all channels have the same ISO interval" );
179+ return - EINVAL ;
180+ }
181+ common_interval = bap_streams [i ]-> qos -> interval ;
182+
183+ /* Check if same audio is sent to all channels */
184+ if (enc_audio .num_ch == 1 ) {
185+ ret = iso_stream_send (enc_audio .data , data_size_pr_stream , bap_streams [i ],
186+ & tx_info [i ], ts_common );
187+ } else {
188+ ret = iso_stream_send (& enc_audio .data [data_size_pr_stream * i ],
189+ data_size_pr_stream , bap_streams [i ], & tx_info [i ],
190+ ts_common );
191+ }
192+
193+ if (ret ) {
194+ /* DBG used here as prints are handled within iso_stream_send */
195+ LOG_DBG ("Failed to send to idx: %d stream: %p, ret: %d " , i , bap_streams [i ],
196+ ret );
197+ continue ;
198+ }
199+
200+ if (!ts_common_acquired ) {
201+ ret = bt_bap_stream_get_tx_sync (bap_streams [i ], & tx_info [i ].iso_tx );
202+ if (ret ) {
203+ LOG_WRN ("Unable to get tx sync. ret: %d stream: %p" , ret ,
204+ bap_streams [i ]);
205+ return ret ;
206+ }
207+
208+ ts_common = tx_info [i ].iso_tx .ts ;
209+ ts_common_acquired = true;
210+ }
172211 }
173212
174- if (ts != 0 && got_tx_sync_ts ) {
213+ if (ts_common_acquired ) {
175214 if (IS_ENABLED (CONFIG_BT_BAP_UNICAST_CLIENT ) &&
176215 !IS_ENABLED (CONFIG_STREAM_BIDIRECTIONAL )) {
177216 struct sdu_ref_msg msg ;
178217
179- msg .timestamp = ts ;
218+ msg .timestamp = ts_common ;
180219 msg .adjust = true;
181220
182221 ret = zbus_chan_pub (& sdu_ref_chan , & msg , K_NO_WAIT );
@@ -186,26 +225,6 @@ int bt_le_audio_tx_send(struct bt_bap_stream **bap_streams, struct le_audio_enco
186225 }
187226 }
188227
189- for (int i = 0 ; i < streams_to_tx ; i ++ ) {
190- if (le_audio_ep_state_check (bap_streams [i ]-> ep , BT_BAP_EP_STATE_STREAMING )) {
191- /* Check if same audio is sent to all channels */
192- if (enc_audio .num_ch == 1 ) {
193- ret = iso_stream_send (enc_audio .data , data_size_pr_stream ,
194- bap_streams [i ], & tx_info [i ]);
195- } else {
196- ret = iso_stream_send (& enc_audio .data [data_size_pr_stream * i ],
197- data_size_pr_stream , bap_streams [i ],
198- & tx_info [i ]);
199- }
200-
201- if (ret ) {
202- /* DBG used here as prints are handled within iso_stream_send */
203- LOG_DBG ("Failed to send to idx: %d stream: %p, ret: %d " , i ,
204- bap_streams [i ], ret );
205- }
206- }
207- }
208-
209228 return 0 ;
210229}
211230
@@ -217,6 +236,7 @@ int bt_le_audio_tx_stream_stopped(uint8_t stream_idx)
217236
218237 atomic_clear (& tx_info [stream_idx ].iso_tx_pool_alloc );
219238 tx_info [stream_idx ].hci_wrn_printed = false;
239+
220240 return 0 ;
221241}
222242
0 commit comments