@@ -98,6 +98,9 @@ static int init_reset(void);
9898 * @return Pointer to lll_df_adv_cfg or NULL if there is no more free memory.
9999 */
100100static struct lll_df_adv_cfg * df_adv_cfg_acquire (void );
101+
102+ static uint8_t cte_info_set (struct ll_adv_set * adv , struct lll_df_adv_cfg * df_cfg , uint8_t * ter_idx ,
103+ struct pdu_adv * * first_pdu );
101104#endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
102105
103106/* @brief Function performs ULL Direction Finding initialization
@@ -334,31 +337,11 @@ uint8_t ll_df_set_cl_cte_tx_enable(uint8_t adv_handle, uint8_t cte_enable)
334337
335338 df_cfg -> is_enabled = 0U ;
336339 } else {
337- struct pdu_cte_info cte_info ;
338- void * hdr_data ;
339-
340340 if (df_cfg -> is_enabled ) {
341341 return BT_HCI_ERR_CMD_DISALLOWED ;
342342 }
343343
344- cte_info .type = df_cfg -> cte_type ;
345- cte_info .time = df_cfg -> cte_length ;
346- hdr_data = (uint8_t * )& cte_info ;
347-
348- err = ull_adv_sync_pdu_alloc (adv , ULL_ADV_PDU_EXTRA_DATA_ALLOC_ALWAYS , & pdu_prev ,
349- & pdu , & extra_data_prev , & extra_data , & ter_idx );
350- if (err ) {
351- return err ;
352- }
353-
354- if (extra_data ) {
355- ull_adv_sync_extra_data_set_clear (extra_data_prev , extra_data ,
356- ULL_ADV_PDU_HDR_FIELD_CTE_INFO , 0 ,
357- df_cfg );
358- }
359-
360- err = ull_adv_sync_pdu_set_clear (lll_sync , pdu_prev , pdu ,
361- ULL_ADV_PDU_HDR_FIELD_CTE_INFO , 0 , hdr_data );
344+ err = cte_info_set (adv , df_cfg , & ter_idx , & pdu );
362345 if (err ) {
363346 return err ;
364347 }
@@ -680,4 +663,182 @@ static struct lll_df_adv_cfg *df_adv_cfg_acquire(void)
680663
681664 return df_adv_cfg ;
682665}
666+
667+ #if (CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX > 1 )
668+ /*
669+ * @brief Function sets content of cte_info field in periodic advertising chain.
670+ *
671+ * The function allocates new PDU (or chain of PDUs) for periodic advertising to
672+ * fill it with information about CTE, that is going to be transmitted with the PDU.
673+ * If there is already allocated PDU, it will be updated to hold information about
674+ * CTE.
675+ *
676+ * @param lll_sync Pointer to periodic advertising sync object.
677+ * @param pdu_prev Pointer to a PDU that is already in use by LLL or was updated with new PDU
678+ * payload.
679+ * @param pdu Pointer to a new head of periodic advertising chain. The pointer may have
680+ * the same value as @p pdu_prev, if payload of PDU pointerd by @p pdu_prev
681+ * was already updated.
682+ * @param cte_count Number of CTEs that should be transmitted in periodic advertising chain.
683+ * @param cte_into Pointer to instence of cte_info stuctuct that is added to PDUs extended
684+ * advertising header.
685+ *
686+ * @return Zero in case of success, other value in case of failure.
687+ */
688+ static uint8_t per_adv_chain_cte_info_set (struct lll_adv_sync * lll_sync , struct pdu_adv * pdu_prev ,
689+ struct pdu_adv * pdu , uint8_t cte_count ,
690+ struct pdu_cte_info * cte_info )
691+ {
692+ uint8_t pdu_add_field_flags ;
693+ struct pdu_adv * pdu_next ;
694+ uint8_t cte_index = 1 ;
695+ bool new_chain ;
696+ uint8_t err ;
697+
698+ new_chain = (pdu_prev == pdu ? false : true);
699+
700+ pdu_add_field_flags = ULL_ADV_PDU_HDR_FIELD_CTE_INFO ;
701+
702+ pdu_prev = lll_adv_pdu_linked_next_get (pdu_prev );
703+
704+ /* Update PDUs in existing chain. Add cte_info to extended advertising header. */
705+ while (pdu_prev ) {
706+ if (new_chain ) {
707+ pdu_next = lll_adv_pdu_alloc_pdu_adv ();
708+ lll_adv_pdu_linked_append (pdu_next , pdu );
709+ pdu = pdu_next ;
710+ } else {
711+ pdu = lll_adv_pdu_linked_next_get (pdu );
712+ }
713+
714+ pdu_next = lll_adv_pdu_linked_next_get (pdu_prev );
715+ /* If all CTEs were added to chain, remove CTE from flags */
716+ if (cte_index >= cte_count ) {
717+ pdu_add_field_flags = 0 ;
718+ } else {
719+ ++ cte_index ;
720+ /* If it is last PDU in existing chain and there are CTE to be included
721+ * add aux_ptr to flags.
722+ */
723+ if (!pdu_next && cte_index < cte_count ) {
724+ pdu_add_field_flags |= ULL_ADV_PDU_HDR_FIELD_AUX_PTR ;
725+ }
726+ }
727+
728+ err = ull_adv_sync_pdu_set_clear (lll_sync , pdu_prev , pdu , pdu_add_field_flags , 0 ,
729+ cte_info );
730+ if (err != BT_HCI_ERR_SUCCESS ) {
731+ /* TODO: implement gracefull error handling, cleanup of
732+ * changed PDUs and notify host abut issue during start of CTE
733+ * transmission.
734+ */
735+ return err ;
736+ }
737+ pdu_prev = pdu_next ;
738+ }
739+
740+ /* If there is missing only one CTE do not add aux_ptr to PDU */
741+ if (cte_count - cte_index >= 2 ) {
742+ pdu_add_field_flags |= ULL_ADV_PDU_HDR_FIELD_AUX_PTR ;
743+ } else {
744+ pdu_add_field_flags = ULL_ADV_PDU_HDR_FIELD_CTE_INFO ;
745+ }
746+
747+ /* Add new PDUs if the number of PDUs in existing chain is lower than requested number
748+ * of CTEs.
749+ */
750+ while (cte_index < cte_count ) {
751+ pdu_prev = pdu ;
752+ pdu = lll_adv_pdu_alloc_pdu_adv ();
753+ if (!pdu ) {
754+ /* TODO: implement graceful error handling, cleanup of
755+ * changed PDUs.
756+ */
757+ return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED ;
758+ }
759+ ull_adv_sync_pdu_init (pdu , pdu_add_field_flags );
760+ ull_adv_sync_pdu_cte_info_set (pdu , cte_info );
761+
762+ /* Link PDU into a chain */
763+ lll_adv_pdu_linked_append (pdu , pdu_prev );
764+
765+ ++ cte_index ;
766+ /* If next PDU in a chain is last PDU, then remove aux_ptr field flag from
767+ * extended advertising header.
768+ */
769+ if (cte_index == cte_count - 1 ) {
770+ pdu_add_field_flags &= (~ULL_ADV_PDU_HDR_FIELD_AUX_PTR );
771+ }
772+ }
773+
774+ return BT_HCI_ERR_SUCCESS ;
775+ }
776+ #endif /* CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX > 1 */
777+
778+ /*
779+ * @brief Function sets content of cte_info field for periodic advertising
780+ *
781+ * @param adv Pointer to periodic advertising set.
782+ * @param df_cfg Pointer to direction finding configuration
783+ * @param[out] ter_idx Pointer used to return index of allocated or updated PDU.
784+ * Index is required for scheduling the PDU for transmission in LLL.
785+ * @param[out] first_pdu Pointer to return address of first PDU in a periodic advertising chain
786+ *
787+ * @return Zero in case of success, other value in case of failure.
788+ */
789+ static uint8_t cte_info_set (struct ll_adv_set * adv , struct lll_df_adv_cfg * df_cfg , uint8_t * ter_idx ,
790+ struct pdu_adv * * first_pdu )
791+ {
792+ struct pdu_adv * pdu_prev , * pdu ;
793+ struct lll_adv_sync * lll_sync ;
794+ struct pdu_cte_info cte_info ;
795+ uint8_t pdu_add_field_flags ;
796+ void * extra_data ;
797+ uint8_t err ;
798+
799+ lll_sync = adv -> lll .sync ;
800+
801+ cte_info .type = df_cfg -> cte_type ;
802+ cte_info .time = df_cfg -> cte_length ;
803+
804+ /* Note: ULL_ADV_PDU_HDR_FIELD_CTE_INFO is just information that extra_data
805+ * is required in case of this ull_adv_sync_pdu_alloc.
806+ * Other flags here do not change anything. It may be changed to use
807+ * true/false flag for extra_data allocation.
808+ */
809+ err = ull_adv_sync_pdu_alloc (adv , ULL_ADV_PDU_EXTRA_DATA_ALLOC_ALWAYS , & pdu_prev , & pdu ,
810+ NULL , & extra_data , ter_idx );
811+ if (err != BT_HCI_ERR_SUCCESS ) {
812+ return err ;
813+ }
814+
815+ ull_adv_sync_extra_data_set_clear (NULL , extra_data , ULL_ADV_PDU_HDR_FIELD_CTE_INFO , 0 ,
816+ df_cfg );
817+
818+ #if (CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX > 1 )
819+ if (df_cfg -> cte_count > 1 ) {
820+ pdu_add_field_flags =
821+ ULL_ADV_PDU_HDR_FIELD_CTE_INFO | ULL_ADV_PDU_HDR_FIELD_AUX_PTR ;
822+ } else
823+ #endif /* CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX > 1 */
824+ {
825+ pdu_add_field_flags = ULL_ADV_PDU_HDR_FIELD_CTE_INFO ;
826+ }
827+
828+ err = ull_adv_sync_pdu_set_clear (lll_sync , pdu_prev , pdu , pdu_add_field_flags , 0 ,
829+ & cte_info );
830+ if (err != BT_HCI_ERR_SUCCESS ) {
831+ return err ;
832+ }
833+
834+ * first_pdu = pdu ;
835+ #if (CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX > 1 )
836+ err = per_adv_chain_cte_info_set (lll_sync , pdu_prev , pdu , df_cfg -> cte_count , & cte_info );
837+ if (err != BT_HCI_ERR_SUCCESS ) {
838+ return err ;
839+ }
840+ #endif /* CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX > 1 */
841+
842+ return BT_HCI_ERR_SUCCESS ;
843+ }
683844#endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
0 commit comments