Skip to content

Commit 68b7b36

Browse files
niag-Oticoncarlescufi
authored andcommitted
Bluetooth: controller: Included guard for lost data in framed PDUs
Improvement for IAL/CIS/FRA/PER/BI-01-C & IAL/CIS/FRA/PER/BI-02-C -- Test appears to fail as the transmitted PDU is packed with less data than is indicated in the segment headers. -- Guards were included to verify that sufficient data exists in the PDU before extracting the segment. General -- Updated timestamps in error SDUs to better approximate the expected timestamps if time information is missing. Signed-off-by: Nirosharn Amarasinghe <[email protected]>
1 parent ffcbc39 commit 68b7b36

File tree

2 files changed

+90
-45
lines changed

2 files changed

+90
-45
lines changed

subsys/bluetooth/controller/ll_sw/isoal.c

Lines changed: 89 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ isoal_status_t isoal_sink_create(
164164

165165
session->handle = handle;
166166
session->framed = framed;
167+
session->sdu_interval = sdu_interval;
167168

168169
/* Todo: Next section computing various constants, should potentially be a
169170
* function in itself as a number of the dependencies could be changed while
@@ -653,6 +654,29 @@ static isoal_status_t isoal_rx_unframed_consume(struct isoal_sink *sink,
653654
return err;
654655
}
655656

657+
/* Check a given segment for errors */
658+
static isoal_sdu_status_t isoal_check_seg_header(struct pdu_iso_sdu_sh *seg_hdr,
659+
uint8_t pdu_size_remaining)
660+
{
661+
if (!seg_hdr) {
662+
/* Segment header is null */
663+
return ISOAL_SDU_STATUS_ERRORS;
664+
}
665+
666+
if (pdu_size_remaining >= PDU_ISO_SEG_HDR_SIZE &&
667+
pdu_size_remaining >= PDU_ISO_SEG_HDR_SIZE + seg_hdr->length) {
668+
669+
/* Valid if there is sufficient data for the segment header and
670+
* there is sufficient data for the required length of the
671+
* segment
672+
*/
673+
return ISOAL_SDU_STATUS_VALID;
674+
}
675+
676+
/* Data is missing from the PDU */
677+
return ISOAL_SDU_STATUS_LOST_DATA;
678+
}
679+
656680
/**
657681
* @brief Consume a framed PDU: Copy contents into SDU(s) and emit to a sink
658682
* @details Destination sink may have an already partially built SDU
@@ -680,6 +704,7 @@ static isoal_status_t isoal_rx_framed_consume(struct isoal_sink *sink,
680704
bool pdu_padding;
681705
bool pdu_err;
682706
bool seq_err;
707+
bool seg_err;
683708

684709
sp = &sink->sdu_production;
685710
session = &sink->session;
@@ -698,52 +723,13 @@ static isoal_status_t isoal_rx_framed_consume(struct isoal_sink *sink,
698723
}
699724

700725
end_of_pdu = ((uint8_t *) pdu_meta->pdu->payload) + pdu_meta->pdu->length - 1;
701-
seg_hdr = (struct pdu_iso_sdu_sh *) pdu_meta->pdu->payload;
702-
703-
if (pdu_err || seq_err) {
704-
/* When one or more ISO Data PDUs are not received, the receiving device may
705-
* discard all SDUs affected by the missing PDUs. Any partially received SDU
706-
* may also be discarded.
707-
*/
708-
next_state = ISOAL_ERR_SPOOL;
709-
710-
/* This maps directly to the HCI ISO Data packet Packet_Status_Flag by way of the
711-
* sdu_status in the SDU emitted.
712-
* BT Core V5.3 : Vol 4 HCI I/F : Part G HCI Func. Spec.:
713-
* 5.4.5 HCI ISO Data packets : Table 5.2 :
714-
* Packet_Status_Flag (in packets sent by the Controller)
715-
* 0b00 Valid data. The complete SDU was received correctly.
716-
* 0b01 Possibly invalid data. The contents of the ISO_SDU_Fragment may contain
717-
* errors or part of the SDU may be missing. This is reported as "data with
718-
* possible errors".
719-
* 0b10 Part(s) of the SDU were not received correctly. This is reported as
720-
* "lost data".
721-
*/
722-
if (seq_err) {
723-
sp->sdu_status |= ISOAL_SDU_STATUS_LOST_DATA;
724-
} else if (pdu_err) {
725-
sp->sdu_status |= meta->status;
726-
}
727-
728-
if (sp->fsm == ISOAL_START) {
729-
/* Sequence number shall be incremented even if an error
730-
* occurs at the beginning.
731-
*/
732-
session->seqn++;
733-
}
734-
735-
/* Flush current SDU with error if any */
736-
err |= isoal_rx_append_to_sdu(sink, pdu_meta, 0, 0, true, false);
737-
738-
/* Skip searching this PDU */
739-
seg_hdr = NULL;
740-
741-
/* Update next state */
742-
sink->sdu_production.fsm = next_state;
743-
}
726+
seg_hdr = (pdu_err || seq_err || pdu_padding) ? NULL :
727+
(struct pdu_iso_sdu_sh *) pdu_meta->pdu->payload;
744728

745-
if (pdu_padding) {
746-
/* Skip searching this PDU */
729+
seg_err = false;
730+
if (seg_hdr && isoal_check_seg_header(seg_hdr, pdu_meta->pdu->length) ==
731+
ISOAL_SDU_STATUS_LOST_DATA) {
732+
seg_err = true;
747733
seg_hdr = NULL;
748734
}
749735

@@ -878,9 +864,67 @@ static isoal_status_t isoal_rx_framed_consume(struct isoal_sink *sink,
878864

879865
if (((uint8_t *) seg_hdr) > end_of_pdu) {
880866
seg_hdr = NULL;
867+
} else if (isoal_check_seg_header(seg_hdr,
868+
(uint8_t)(end_of_pdu + 1 - ((uint8_t *) seg_hdr))) ==
869+
ISOAL_SDU_STATUS_LOST_DATA) {
870+
seg_err = true;
871+
seg_hdr = NULL;
881872
}
882873
}
883874

875+
if (pdu_err || seq_err || seg_err) {
876+
/* When one or more ISO Data PDUs are not received, the receiving device may
877+
* discard all SDUs affected by the missing PDUs. Any partially received SDU
878+
* may also be discarded.
879+
*/
880+
next_state = ISOAL_ERR_SPOOL;
881+
882+
/* This maps directly to the HCI ISO Data packet Packet_Status_Flag by way of the
883+
* sdu_status in the SDU emitted.
884+
* BT Core V5.3 : Vol 4 HCI I/F : Part G HCI Func. Spec.:
885+
* 5.4.5 HCI ISO Data packets : Table 5.2 :
886+
* Packet_Status_Flag (in packets sent by the Controller)
887+
* 0b00 Valid data. The complete SDU was received correctly.
888+
* 0b01 Possibly invalid data. The contents of the ISO_SDU_Fragment may contain
889+
* errors or part of the SDU may be missing. This is reported as "data with
890+
* possible errors".
891+
* 0b10 Part(s) of the SDU were not received correctly. This is reported as
892+
* "lost data".
893+
*/
894+
if (seq_err || seg_err) {
895+
sp->sdu_status |= ISOAL_SDU_STATUS_LOST_DATA;
896+
} else if (pdu_err) {
897+
sp->sdu_status |= meta->status;
898+
}
899+
900+
if (sp->fsm == ISOAL_START) {
901+
/* Sequence number should be incremented if an error
902+
* occurs at the beginning.
903+
*/
904+
session->seqn++;
905+
906+
if (sdu->timestamp == 0) {
907+
/* Last timestamp is not valid so set an
908+
* approximate timestamp
909+
*/
910+
anchorpoint = meta->timestamp;
911+
latency = session->latency_framed;
912+
timestamp = anchorpoint + latency;
913+
914+
sdu->timestamp = timestamp;
915+
} else {
916+
/* Advance the timestamp by an SDU interval */
917+
sdu->timestamp += session->sdu_interval;
918+
}
919+
}
920+
921+
/* Flush current SDU with error if any */
922+
err |= isoal_rx_append_to_sdu(sink, pdu_meta, 0, 0, true, false);
923+
924+
/* Update next state */
925+
sink->sdu_production.fsm = next_state;
926+
}
927+
884928
sp->prev_pdu_id = meta->payload_number;
885929

886930
return err;

subsys/bluetooth/controller/ll_sw/isoal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ struct isoal_sink_session {
226226
uint16_t handle;
227227
uint8_t pdus_per_sdu;
228228
uint8_t framed;
229+
uint32_t sdu_interval;
229230
uint32_t latency_unframed;
230231
uint32_t latency_framed;
231232
};

0 commit comments

Comments
 (0)