@@ -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 ;
0 commit comments