@@ -250,14 +250,14 @@ isoal_status_t isoal_sink_create(
250
250
*/
251
251
if (role == BT_CONN_ROLE_PERIPHERAL ) {
252
252
isoal_global .sink_state [* hdl ].session .latency_unframed =
253
- stream_sync_delay + ((flush_timeout - 1 ) * iso_interval_us );
253
+ stream_sync_delay + ((flush_timeout - 1UL ) * iso_interval_us );
254
254
255
255
isoal_global .sink_state [* hdl ].session .latency_framed =
256
256
stream_sync_delay + sdu_interval + (flush_timeout * iso_interval_us );
257
257
} else if (role == BT_CONN_ROLE_CENTRAL ) {
258
258
isoal_global .sink_state [* hdl ].session .latency_unframed =
259
259
stream_sync_delay - group_sync_delay -
260
- (((iso_interval_us / sdu_interval ) - 1 ) * iso_interval_us );
260
+ (((iso_interval_us / sdu_interval ) - 1UL ) * iso_interval_us );
261
261
262
262
isoal_global .sink_state [* hdl ].session .latency_framed =
263
263
stream_sync_delay - group_sync_delay ;
@@ -921,7 +921,7 @@ static isoal_status_t isoal_rx_framed_consume(struct isoal_sink *sink,
921
921
seq_err = (meta -> payload_number != (sp -> prev_pdu_id + 1 ));
922
922
}
923
923
924
- end_of_pdu = ((uint8_t * ) pdu_meta -> pdu -> payload ) + pdu_meta -> pdu -> len - 1 ;
924
+ end_of_pdu = ((uint8_t * ) pdu_meta -> pdu -> payload ) + pdu_meta -> pdu -> len - 1UL ;
925
925
seg_hdr = (pdu_err || seq_err || pdu_padding ) ? NULL :
926
926
(struct pdu_iso_sdu_sh * ) pdu_meta -> pdu -> payload ;
927
927
@@ -1064,7 +1064,7 @@ static isoal_status_t isoal_rx_framed_consume(struct isoal_sink *sink,
1064
1064
if (((uint8_t * ) seg_hdr ) > end_of_pdu ) {
1065
1065
seg_hdr = NULL ;
1066
1066
} else if (isoal_check_seg_header (seg_hdr ,
1067
- (uint8_t )(end_of_pdu + 1 - ((uint8_t * ) seg_hdr ))) ==
1067
+ (uint8_t )(end_of_pdu + 1UL - ((uint8_t * ) seg_hdr ))) ==
1068
1068
ISOAL_SDU_STATUS_LOST_DATA ) {
1069
1069
seg_err = true;
1070
1070
seg_hdr = NULL ;
@@ -1457,10 +1457,17 @@ static isoal_status_t isoal_tx_pdu_emit(const struct isoal_source *source_ctx,
1457
1457
return status ;
1458
1458
}
1459
1459
1460
- /* Allocates a new PDU only if the previous PDU was emitted */
1460
+ /**
1461
+ * Allocates a new PDU only if the previous PDU was emitted
1462
+ * @param[in] source ISO-AL source reference
1463
+ * @param[in] tx_sdu SDU fragment to be transmitted (can be NULL)
1464
+ * @return Error status of operation
1465
+ */
1461
1466
static isoal_status_t isoal_tx_allocate_pdu (struct isoal_source * source ,
1462
1467
const struct isoal_sdu_tx * tx_sdu )
1463
1468
{
1469
+ ARG_UNUSED (tx_sdu );
1470
+
1464
1471
struct isoal_source_session * session ;
1465
1472
struct isoal_pdu_production * pp ;
1466
1473
struct isoal_pdu_produced * pdu ;
@@ -2050,16 +2057,15 @@ static isoal_status_t isoal_tx_framed_produce(struct isoal_source *source,
2050
2057
2051
2058
err |= err_emit ;
2052
2059
2053
- /* TODO: Send padding PDU(s) if required
2054
- *
2055
- * BT Core V5.3 : Vol 6 Low Energy Controller : Part G IS0-AL:
2060
+ /* BT Core V5.3 : Vol 6 Low Energy Controller : Part G IS0-AL:
2056
2061
* 2 ISOAL Features :
2057
2062
* Padding is required when the data does not add up to the
2058
2063
* configured number of PDUs that are specified in the BN
2059
2064
* parameter per CIS or BIS event.
2060
2065
*
2061
2066
* When padding PDUs as opposed to null PDUs are required for
2062
- * framed production is not clear.
2067
+ * framed production is not clear. Padding PDUs will be released
2068
+ * on the next event prepare trigger.
2063
2069
*/
2064
2070
padding_pdu = false;
2065
2071
zero_length_sdu = false;
@@ -2080,25 +2086,72 @@ static isoal_status_t isoal_tx_framed_event_prepare_handle(isoal_source_handle_t
2080
2086
{
2081
2087
struct isoal_source_session * session ;
2082
2088
struct isoal_pdu_production * pp ;
2089
+ uint64_t first_event_payload ;
2083
2090
struct isoal_source * source ;
2084
2091
uint64_t last_event_payload ;
2092
+ isoal_status_t err_alloc ;
2093
+ bool release_padding ;
2085
2094
isoal_status_t err ;
2086
2095
2087
2096
err = ISOAL_STATUS_OK ;
2097
+ err_alloc = ISOAL_STATUS_OK ;
2098
+ release_padding = false;
2088
2099
2089
2100
source = & isoal_global .source_state [source_hdl ];
2090
2101
session = & source -> session ;
2091
2102
pp = & source -> pdu_production ;
2092
- last_event_payload = (session -> burst_number * (event_count + 1 )) - 1 ;
2103
+ first_event_payload = (session -> burst_number * event_count );
2104
+ last_event_payload = (session -> burst_number * (event_count + 1ULL )) - 1ULL ;
2093
2105
2094
2106
if (pp -> pdu_available > 0 &&
2095
2107
pp -> payload_number <= last_event_payload ) {
2096
2108
/* Pending PDU that should be released for framed TX */
2097
2109
err = isoal_tx_try_emit_pdu (source , true, PDU_BIS_LLID_FRAMED );
2098
2110
}
2099
2111
2100
- if (pp -> payload_number < last_event_payload + 1 ) {
2101
- pp -> payload_number = last_event_payload + 1 ;
2112
+ if (pp -> mode != ISOAL_PRODUCTION_MODE_DISABLED ) {
2113
+ /* BT Core V5.3 : Vol 6 Low Energy Controller :
2114
+ * Part G IS0-AL:
2115
+ *
2116
+ * 2 ISOAL Features :
2117
+ * Padding is required when the data does not add up to the
2118
+ * configured number of PDUs that are specified in the BN
2119
+ * parameter per CIS or BIS event.
2120
+ *
2121
+ * There is some lack of clarity in the specifications as to why
2122
+ * padding PDUs should be used as opposed to null PDUs. However
2123
+ * if a payload is not available, the LL must default to waiting
2124
+ * for the flush timeout before it can proceed to the next
2125
+ * payload.
2126
+ *
2127
+ * This means a loss of retransmission capacity for future
2128
+ * payloads that could exist. Sending padding PDUs will prevent
2129
+ * this loss while not resulting in additional SDUs on the
2130
+ * receiver. However it does incur the allocation and handling
2131
+ * overhead on the transmitter.
2132
+ *
2133
+ * As an interpretation of the specification, padding PDUs will
2134
+ * only be released if an SDU has been received in the current
2135
+ * event.
2136
+ */
2137
+ if (pp -> payload_number > first_event_payload ) {
2138
+ release_padding = true;
2139
+ }
2140
+ }
2141
+
2142
+ if (release_padding ) {
2143
+ while (!err && !err_alloc && (pp -> payload_number < last_event_payload + 1ULL )) {
2144
+ err_alloc = isoal_tx_allocate_pdu (source , NULL );
2145
+
2146
+ err = isoal_tx_try_emit_pdu (source , true, PDU_BIS_LLID_FRAMED );
2147
+ }
2148
+ }
2149
+
2150
+ /* Not possible to recover if allocation or emit fails here*/
2151
+ LL_ASSERT (!(err || err_alloc ));
2152
+
2153
+ if (pp -> payload_number < last_event_payload + 1ULL ) {
2154
+ pp -> payload_number = last_event_payload + 1ULL ;
2102
2155
}
2103
2156
2104
2157
return err ;
0 commit comments