@@ -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
@@ -319,31 +322,11 @@ uint8_t ll_df_set_cl_cte_tx_enable(uint8_t adv_handle, uint8_t cte_enable)
319322
320323 df_cfg -> is_enabled = 0U ;
321324 } else {
322- struct pdu_cte_info cte_info ;
323- void * hdr_data ;
324-
325325 if (df_cfg -> is_enabled ) {
326326 return BT_HCI_ERR_CMD_DISALLOWED ;
327327 }
328328
329- cte_info .type = df_cfg -> cte_type ;
330- cte_info .time = df_cfg -> cte_length ;
331- hdr_data = (uint8_t * )& cte_info ;
332-
333- err = ull_adv_sync_pdu_alloc (adv , ULL_ADV_PDU_EXTRA_DATA_ALLOC_ALWAYS , & pdu_prev ,
334- & pdu , & extra_data_prev , & extra_data , & ter_idx );
335- if (err ) {
336- return err ;
337- }
338-
339- if (extra_data ) {
340- ull_adv_sync_extra_data_set_clear (extra_data_prev , extra_data ,
341- ULL_ADV_PDU_HDR_FIELD_CTE_INFO , 0 ,
342- df_cfg );
343- }
344-
345- err = ull_adv_sync_pdu_set_clear (lll_sync , pdu_prev , pdu ,
346- ULL_ADV_PDU_HDR_FIELD_CTE_INFO , 0 , hdr_data );
329+ err = cte_info_set (adv , df_cfg , & ter_idx , & pdu );
347330 if (err ) {
348331 return err ;
349332 }
@@ -665,4 +648,182 @@ static struct lll_df_adv_cfg *df_adv_cfg_acquire(void)
665648
666649 return df_adv_cfg ;
667650}
651+
652+ #if (CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX > 1 )
653+ /*
654+ * @brief Function sets content of cte_info field in periodic advertising chain.
655+ *
656+ * The function allocates new PDU (or chain of PDUs) for periodic advertising to
657+ * fill it with information about CTE, that is going to be transmitted with the PDU.
658+ * If there is already allocated PDU, it will be updated to hold information about
659+ * CTE.
660+ *
661+ * @param lll_sync Pointer to periodic advertising sync object.
662+ * @param pdu_prev Pointer to a PDU that is already in use by LLL or was updated with new PDU
663+ * payload.
664+ * @param pdu Pointer to a new head of periodic advertising chain. The pointer may have
665+ * the same value as @p pdu_prev, if payload of PDU pointerd by @p pdu_prev
666+ * was already updated.
667+ * @param cte_count Number of CTEs that should be transmitted in periodic advertising chain.
668+ * @param cte_into Pointer to instence of cte_info stuctuct that is added to PDUs extended
669+ * advertising header.
670+ *
671+ * @return Zero in case of success, other value in case of failure.
672+ */
673+ static uint8_t per_adv_chain_cte_info_set (struct lll_adv_sync * lll_sync , struct pdu_adv * pdu_prev ,
674+ struct pdu_adv * pdu , uint8_t cte_count ,
675+ struct pdu_cte_info * cte_info )
676+ {
677+ uint8_t pdu_add_field_flags ;
678+ struct pdu_adv * pdu_next ;
679+ uint8_t cte_index = 1 ;
680+ bool new_chain ;
681+ uint8_t err ;
682+
683+ new_chain = (pdu_prev == pdu ? false : true);
684+
685+ pdu_add_field_flags = ULL_ADV_PDU_HDR_FIELD_CTE_INFO ;
686+
687+ pdu_prev = lll_adv_pdu_linked_next_get (pdu_prev );
688+
689+ /* Update PDUs in existing chain. Add cte_info to extended advertising header. */
690+ while (pdu_prev ) {
691+ if (new_chain ) {
692+ pdu_next = lll_adv_pdu_alloc_pdu_adv ();
693+ lll_adv_pdu_linked_append (pdu_next , pdu );
694+ pdu = pdu_next ;
695+ } else {
696+ pdu = lll_adv_pdu_linked_next_get (pdu );
697+ }
698+
699+ pdu_next = lll_adv_pdu_linked_next_get (pdu_prev );
700+ /* If all CTEs were added to chain, remove CTE from flags */
701+ if (cte_index >= cte_count ) {
702+ pdu_add_field_flags = 0 ;
703+ } else {
704+ ++ cte_index ;
705+ /* If it is last PDU in existing chain and there are CTE to be included
706+ * add aux_ptr to flags.
707+ */
708+ if (!pdu_next && cte_index < cte_count ) {
709+ pdu_add_field_flags |= ULL_ADV_PDU_HDR_FIELD_AUX_PTR ;
710+ }
711+ }
712+
713+ err = ull_adv_sync_pdu_set_clear (lll_sync , pdu_prev , pdu , pdu_add_field_flags , 0 ,
714+ cte_info );
715+ if (err != BT_HCI_ERR_SUCCESS ) {
716+ /* TODO: implement gracefull error handling, cleanup of
717+ * changed PDUs and notify host abut issue during start of CTE
718+ * transmission.
719+ */
720+ return err ;
721+ }
722+ pdu_prev = pdu_next ;
723+ }
724+
725+ /* If there is missing only one CTE do not add aux_ptr to PDU */
726+ if (cte_count - cte_index >= 2 ) {
727+ pdu_add_field_flags |= ULL_ADV_PDU_HDR_FIELD_AUX_PTR ;
728+ } else {
729+ pdu_add_field_flags = ULL_ADV_PDU_HDR_FIELD_CTE_INFO ;
730+ }
731+
732+ /* Add new PDUs if the number of PDUs in existing chain is lower than requested number
733+ * of CTEs.
734+ */
735+ while (cte_index < cte_count ) {
736+ pdu_prev = pdu ;
737+ pdu = lll_adv_pdu_alloc_pdu_adv ();
738+ if (!pdu ) {
739+ /* TODO: implement graceful error handling, cleanup of
740+ * changed PDUs.
741+ */
742+ return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED ;
743+ }
744+ ull_adv_sync_pdu_init (pdu , pdu_add_field_flags );
745+ ull_adv_sync_pdu_cte_info_set (pdu , cte_info );
746+
747+ /* Link PDU into a chain */
748+ lll_adv_pdu_linked_append (pdu , pdu_prev );
749+
750+ ++ cte_index ;
751+ /* If next PDU in a chain is last PDU, then remove aux_ptr field flag from
752+ * extended advertising header.
753+ */
754+ if (cte_index == cte_count - 1 ) {
755+ pdu_add_field_flags &= (~ULL_ADV_PDU_HDR_FIELD_AUX_PTR );
756+ }
757+ }
758+
759+ return BT_HCI_ERR_SUCCESS ;
760+ }
761+ #endif /* CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX > 1 */
762+
763+ /*
764+ * @brief Function sets content of cte_info field for periodic advertising
765+ *
766+ * @param adv Pointer to periodic advertising set.
767+ * @param df_cfg Pointer to direction finding configuration
768+ * @param[out] ter_idx Pointer used to return index of allocated or updated PDU.
769+ * Index is required for scheduling the PDU for transmission in LLL.
770+ * @param[out] first_pdu Pointer to return address of first PDU in a periodic advertising chain
771+ *
772+ * @return Zero in case of success, other value in case of failure.
773+ */
774+ static uint8_t cte_info_set (struct ll_adv_set * adv , struct lll_df_adv_cfg * df_cfg , uint8_t * ter_idx ,
775+ struct pdu_adv * * first_pdu )
776+ {
777+ struct pdu_adv * pdu_prev , * pdu ;
778+ struct lll_adv_sync * lll_sync ;
779+ struct pdu_cte_info cte_info ;
780+ uint8_t pdu_add_field_flags ;
781+ void * extra_data ;
782+ uint8_t err ;
783+
784+ lll_sync = adv -> lll .sync ;
785+
786+ cte_info .type = df_cfg -> cte_type ;
787+ cte_info .time = df_cfg -> cte_length ;
788+
789+ /* Note: ULL_ADV_PDU_HDR_FIELD_CTE_INFO is just information that extra_data
790+ * is required in case of this ull_adv_sync_pdu_alloc.
791+ * Other flags here do not change anything. It may be changed to use
792+ * true/false flag for extra_data allocation.
793+ */
794+ err = ull_adv_sync_pdu_alloc (adv , ULL_ADV_PDU_EXTRA_DATA_ALLOC_ALWAYS , & pdu_prev , & pdu ,
795+ NULL , & extra_data , ter_idx );
796+ if (err != BT_HCI_ERR_SUCCESS ) {
797+ return err ;
798+ }
799+
800+ ull_adv_sync_extra_data_set_clear (NULL , extra_data , ULL_ADV_PDU_HDR_FIELD_CTE_INFO , 0 ,
801+ df_cfg );
802+
803+ #if (CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX > 1 )
804+ if (df_cfg -> cte_count > 1 ) {
805+ pdu_add_field_flags =
806+ ULL_ADV_PDU_HDR_FIELD_CTE_INFO | ULL_ADV_PDU_HDR_FIELD_AUX_PTR ;
807+ } else
808+ #endif /* CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX > 1 */
809+ {
810+ pdu_add_field_flags = ULL_ADV_PDU_HDR_FIELD_CTE_INFO ;
811+ }
812+
813+ err = ull_adv_sync_pdu_set_clear (lll_sync , pdu_prev , pdu , pdu_add_field_flags , 0 ,
814+ & cte_info );
815+ if (err != BT_HCI_ERR_SUCCESS ) {
816+ return err ;
817+ }
818+
819+ * first_pdu = pdu ;
820+ #if (CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX > 1 )
821+ err = per_adv_chain_cte_info_set (lll_sync , pdu_prev , pdu , df_cfg -> cte_count , & cte_info );
822+ if (err != BT_HCI_ERR_SUCCESS ) {
823+ return err ;
824+ }
825+ #endif /* CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX > 1 */
826+
827+ return BT_HCI_ERR_SUCCESS ;
828+ }
668829#endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
0 commit comments