@@ -367,7 +367,15 @@ static int hfp_ag_next_step(struct bt_hfp_ag *ag, bt_hfp_ag_tx_cb_t cb, void *us
367367 tx -> user_data = user_data ;
368368 tx -> err = 0 ;
369369
370- k_fifo_put (& ag_tx_notify , tx );
370+ hfp_ag_lock (ag );
371+ if (atomic_test_bit (ag -> flags , BT_HFP_AG_AT_PROCESS )) {
372+ sys_slist_append (& ag -> tx_submit_pending , & tx -> node );
373+ } else {
374+ sys_slist_append (& ag -> tx_pending , & tx -> node );
375+ /* Always active tx work */
376+ k_work_reschedule (& ag -> tx_work , K_NO_WAIT );
377+ }
378+ hfp_ag_unlock (ag );
371379
372380 return 0 ;
373381}
@@ -835,6 +843,70 @@ static int hfp_ag_send(struct bt_hfp_ag *ag, struct bt_ag_tx *tx)
835843 return err ;
836844}
837845
846+ static void bt_ag_notify_work (struct k_work * work );
847+
848+ struct k_work ag_notify_work = Z_WORK_INITIALIZER (bt_ag_notify_work );
849+
850+ static void bt_ag_notify_work (struct k_work * work )
851+ {
852+ struct bt_ag_tx * tx ;
853+ bt_hfp_ag_tx_cb_t cb ;
854+ struct bt_hfp_ag * ag ;
855+ void * user_data ;
856+ bt_hfp_state_t state ;
857+ int err ;
858+
859+ tx = (struct bt_ag_tx * )k_fifo_get (& ag_tx_notify , K_NO_WAIT );
860+
861+ if (tx == NULL ) {
862+ return ;
863+ }
864+
865+ cb = tx -> cb ;
866+ ag = tx -> ag ;
867+ user_data = tx -> user_data ;
868+ err = tx -> err ;
869+
870+ bt_ag_tx_free (tx );
871+
872+ if (err < 0 ) {
873+ state = ag -> state ;
874+ if ((state != BT_HFP_DISCONNECTED ) && (state != BT_HFP_DISCONNECTING )) {
875+ bt_hfp_ag_set_state (ag , BT_HFP_DISCONNECTING );
876+ bt_rfcomm_dlc_disconnect (& ag -> rfcomm_dlc );
877+ }
878+ }
879+
880+ if (cb != NULL ) {
881+ cb (ag , user_data );
882+ }
883+
884+ if (!k_fifo_is_empty (& ag_tx_notify )) {
885+ /* Submit worker if the fifo ag_tx_notify is not empty. */
886+ k_work_submit (& ag_notify_work );
887+ }
888+ }
889+
890+ static void bt_ag_tx_notify (struct bt_ag_tx * tx )
891+ {
892+ k_fifo_put (& ag_tx_notify , tx );
893+
894+ k_work_submit (& ag_notify_work );
895+ }
896+
897+ static void bt_ag_tx_done_with_err (struct bt_hfp_ag * ag , struct bt_ag_tx * tx , int err )
898+ {
899+ sys_slist_find_and_remove (& ag -> tx_pending , & tx -> node );
900+ tx -> err = err ;
901+ bt_ag_tx_notify (tx );
902+ /* Clear the tx ongoing flag */
903+ if (!atomic_test_and_clear_bit (ag -> flags , BT_HFP_AG_TX_ONGOING )) {
904+ LOG_WRN ("tx ongoing flag is not set" );
905+ }
906+ /* Due to the work is done, restart the tx work */
907+ k_work_reschedule (& ag -> tx_work , K_NO_WAIT );
908+ }
909+
838910static void bt_ag_tx_work (struct k_work * work )
839911{
840912 struct k_work_delayable * dwork = k_work_delayable_from_work (work );
@@ -859,20 +931,21 @@ static void bt_ag_tx_work(struct k_work *work)
859931 tx = CONTAINER_OF (node , struct bt_ag_tx , node );
860932
861933 if (!atomic_test_and_set_bit (ag -> flags , BT_HFP_AG_TX_ONGOING )) {
934+ int err ;
935+
862936 LOG_DBG ("AG %p sending tx %p" , ag , tx );
863- int err = hfp_ag_send (ag , tx );
937+
938+ if (tx -> buf == NULL ) {
939+ /* Goto next state and remove the current tx */
940+ bt_ag_tx_done_with_err (ag , tx , 0 );
941+ goto unlock ;
942+ }
943+
944+ err = hfp_ag_send (ag , tx );
864945
865946 if (err < 0 ) {
866947 LOG_ERR ("Rfcomm send error :(%d)" , err );
867- sys_slist_find_and_remove (& ag -> tx_pending , & tx -> node );
868- tx -> err = err ;
869- k_fifo_put (& ag_tx_notify , tx );
870- /* Clear the tx ongoing flag */
871- if (!atomic_test_and_clear_bit (ag -> flags , BT_HFP_AG_TX_ONGOING )) {
872- LOG_WRN ("tx ongoing flag is not set" );
873- }
874- /* Due to the work is failed, restart the tx work */
875- k_work_reschedule (& ag -> tx_work , K_NO_WAIT );
948+ bt_ag_tx_done_with_err (ag , tx , err );
876949 }
877950 }
878951
@@ -3458,29 +3531,47 @@ static void hfp_ag_connected(struct bt_rfcomm_dlc *dlc)
34583531 LOG_DBG ("AG %p" , ag );
34593532}
34603533
3534+ static struct bt_ag_tx * ag_get_tx (struct bt_hfp_ag * ag , sys_slist_t * list )
3535+ {
3536+ sys_snode_t * node ;
3537+
3538+ hfp_ag_lock (ag );
3539+ node = sys_slist_get (list );
3540+ hfp_ag_unlock (ag );
3541+ if (node == NULL ) {
3542+ return NULL ;
3543+ }
3544+
3545+ return CONTAINER_OF (node , struct bt_ag_tx , node );
3546+ }
3547+
34613548static void hfp_ag_disconnected (struct bt_rfcomm_dlc * dlc )
34623549{
34633550 struct bt_hfp_ag * ag = CONTAINER_OF (dlc , struct bt_hfp_ag , rfcomm_dlc );
3464- sys_snode_t * node ;
34653551 struct bt_ag_tx * tx ;
34663552 struct bt_hfp_ag_call * call ;
34673553
34683554 k_work_cancel_delayable (& ag -> tx_work );
34693555
3470- hfp_ag_lock (ag );
3471- node = sys_slist_get (& ag -> tx_pending );
3472- hfp_ag_unlock (ag );
3473- tx = CONTAINER_OF (node , struct bt_ag_tx , node );
3474- while (tx ) {
3475- if (tx -> buf && !atomic_test_and_clear_bit (ag -> flags , BT_HFP_AG_TX_ONGOING )) {
3556+ tx = ag_get_tx (ag , & ag -> tx_pending );
3557+ while (tx != NULL ) {
3558+ if ((tx -> buf != NULL ) &&
3559+ !atomic_test_and_clear_bit (ag -> flags , BT_HFP_AG_TX_ONGOING )) {
34763560 net_buf_unref (tx -> buf );
34773561 }
34783562 tx -> err = - ESHUTDOWN ;
3479- k_fifo_put (& ag_tx_notify , tx );
3480- hfp_ag_lock (ag );
3481- node = sys_slist_get (& ag -> tx_pending );
3482- hfp_ag_unlock (ag );
3483- tx = CONTAINER_OF (node , struct bt_ag_tx , node );
3563+ bt_ag_tx_notify (tx );
3564+ tx = ag_get_tx (ag , & ag -> tx_pending );
3565+ }
3566+
3567+ tx = ag_get_tx (ag , & ag -> tx_submit_pending );
3568+ while (tx != NULL ) {
3569+ if (tx -> buf != NULL ) {
3570+ net_buf_unref (tx -> buf );
3571+ }
3572+ tx -> err = - ESHUTDOWN ;
3573+ bt_ag_tx_notify (tx );
3574+ tx = ag_get_tx (ag , & ag -> tx_submit_pending );
34843575 }
34853576
34863577 bt_hfp_ag_set_state (ag , BT_HFP_DISCONNECTED );
@@ -3502,6 +3593,31 @@ static void hfp_ag_disconnected(struct bt_rfcomm_dlc *dlc)
35023593 LOG_DBG ("AG %p" , ag );
35033594}
35043595
3596+ static void hfp_ag_preprocess_at_cmd (struct bt_hfp_ag * ag )
3597+ {
3598+ atomic_set_bit (ag -> flags , BT_HFP_AG_AT_PROCESS );
3599+ }
3600+
3601+ static void hfp_ag_postprocess_at_cmd (struct bt_hfp_ag * ag )
3602+ {
3603+ sys_snode_t * node ;
3604+
3605+ if (!atomic_test_and_clear_bit (ag -> flags , BT_HFP_AG_AT_PROCESS )) {
3606+ LOG_WRN ("No AT CMD is processing" );
3607+ }
3608+
3609+ hfp_ag_lock (ag );
3610+ node = sys_slist_get (& ag -> tx_submit_pending );
3611+ while (node != NULL ) {
3612+ sys_slist_append (& ag -> tx_pending , node );
3613+ node = sys_slist_get (& ag -> tx_submit_pending );
3614+ }
3615+ hfp_ag_unlock (ag );
3616+
3617+ /* Always active tx work */
3618+ k_work_reschedule (& ag -> tx_work , K_NO_WAIT );
3619+ }
3620+
35053621static void hfp_ag_recv (struct bt_rfcomm_dlc * dlc , struct net_buf * buf )
35063622{
35073623 struct bt_hfp_ag * ag = CONTAINER_OF (dlc , struct bt_hfp_ag , rfcomm_dlc );
@@ -3512,6 +3628,8 @@ static void hfp_ag_recv(struct bt_rfcomm_dlc *dlc, struct net_buf *buf)
35123628
35133629 LOG_HEXDUMP_DBG (data , len , "Received:" );
35143630
3631+ hfp_ag_preprocess_at_cmd (ag );
3632+
35153633 for (uint32_t index = 0 ; index < ARRAY_SIZE (cmd_handlers ); index ++ ) {
35163634 if (strlen (cmd_handlers [index ].cmd ) > len ) {
35173635 continue ;
@@ -3545,48 +3663,13 @@ static void hfp_ag_recv(struct bt_rfcomm_dlc *dlc, struct net_buf *buf)
35453663 err = hfp_ag_send_data (ag , cb , NULL , "\r\n%s\r\n" , (err == 0 ) ? "OK" : "ERROR" );
35463664 }
35473665
3666+ hfp_ag_postprocess_at_cmd (ag );
3667+
35483668 if (err != 0 ) {
35493669 LOG_ERR ("HFP AG send response err :(%d)" , err );
35503670 }
35513671}
35523672
3553- static void bt_hfp_ag_thread (void * p1 , void * p2 , void * p3 )
3554- {
3555- struct bt_ag_tx * tx ;
3556- bt_hfp_ag_tx_cb_t cb ;
3557- struct bt_hfp_ag * ag ;
3558- void * user_data ;
3559- bt_hfp_state_t state ;
3560- int err ;
3561-
3562- while (true) {
3563- tx = (struct bt_ag_tx * )k_fifo_get (& ag_tx_notify , K_FOREVER );
3564-
3565- if (tx == NULL ) {
3566- continue ;
3567- }
3568-
3569- cb = tx -> cb ;
3570- ag = tx -> ag ;
3571- user_data = tx -> user_data ;
3572- err = tx -> err ;
3573-
3574- bt_ag_tx_free (tx );
3575-
3576- if (err < 0 ) {
3577- state = ag -> state ;
3578- if ((state != BT_HFP_DISCONNECTED ) && (state != BT_HFP_DISCONNECTING )) {
3579- bt_hfp_ag_set_state (ag , BT_HFP_DISCONNECTING );
3580- bt_rfcomm_dlc_disconnect (& ag -> rfcomm_dlc );
3581- }
3582- }
3583-
3584- if (cb ) {
3585- cb (ag , user_data );
3586- }
3587- }
3588- }
3589-
35903673static void hfp_ag_sent (struct bt_rfcomm_dlc * dlc , int err )
35913674{
35923675 struct bt_hfp_ag * ag = CONTAINER_OF (dlc , struct bt_hfp_ag , rfcomm_dlc );
@@ -3615,7 +3698,7 @@ static void hfp_ag_sent(struct bt_rfcomm_dlc *dlc, int err)
36153698 k_work_reschedule (& ag -> tx_work , K_NO_WAIT );
36163699
36173700 tx -> err = err ;
3618- k_fifo_put ( & ag_tx_notify , tx );
3701+ bt_ag_tx_notify ( tx );
36193702}
36203703
36213704static const char * bt_ag_get_call_state_string (bt_hfp_call_state_t call_state )
@@ -3793,6 +3876,7 @@ static void bt_ag_send_ok_code(struct bt_hfp_ag *ag)
37933876 if (hfp_ag_send_data (ag , NULL , NULL , "\r\nOK\r\n" ) != 0 ) {
37943877 LOG_ERR ("Failed to send OK code" );
37953878 }
3879+ hfp_ag_postprocess_at_cmd (ag );
37963880}
37973881
37983882static void bt_ag_ongoing_call_work (struct k_work * work )
@@ -3811,8 +3895,6 @@ static void bt_ag_ongoing_call_work(struct k_work *work)
38113895 bt_ag_send_ok_code (ag );
38123896}
38133897
3814- static K_KERNEL_STACK_MEMBER (ag_thread_stack , CONFIG_BT_HFP_AG_THREAD_STACK_SIZE ) ;
3815-
38163898static struct bt_hfp_ag * hfp_ag_create (struct bt_conn * conn )
38173899{
38183900 static struct bt_rfcomm_dlc_ops ops = {
@@ -3821,30 +3903,11 @@ static struct bt_hfp_ag *hfp_ag_create(struct bt_conn *conn)
38213903 .recv = hfp_ag_recv ,
38223904 .sent = hfp_ag_sent ,
38233905 };
3824- static k_tid_t ag_thread_id ;
3825- static struct k_thread ag_thread ;
38263906 size_t index ;
38273907 struct bt_hfp_ag * ag ;
38283908
38293909 LOG_DBG ("conn %p" , conn );
38303910
3831- if (ag_thread_id == NULL ) {
3832-
3833- k_fifo_init (& ag_tx_free );
3834- k_fifo_init (& ag_tx_notify );
3835-
3836- for (index = 0 ; index < ARRAY_SIZE (ag_tx ); index ++ ) {
3837- k_fifo_put (& ag_tx_free , & ag_tx [index ]);
3838- }
3839-
3840- ag_thread_id = k_thread_create (
3841- & ag_thread , ag_thread_stack , K_KERNEL_STACK_SIZEOF (ag_thread_stack ),
3842- bt_hfp_ag_thread , NULL , NULL , NULL ,
3843- K_PRIO_COOP (CONFIG_BT_HFP_AG_THREAD_PRIO ), 0 , K_NO_WAIT );
3844- __ASSERT (ag_thread_id , "Cannot create thread for AG" );
3845- k_thread_name_set (ag_thread_id , "HFP AG" );
3846- }
3847-
38483911 index = (size_t )bt_conn_index (conn );
38493912 __ASSERT (index < ARRAY_SIZE (bt_hfp_ag_pool ), "Conn index is out of bounds" );
38503913
@@ -3857,6 +3920,7 @@ static struct bt_hfp_ag *hfp_ag_create(struct bt_conn *conn)
38573920 (void )memset (ag , 0 , sizeof (struct bt_hfp_ag ));
38583921
38593922 sys_slist_init (& ag -> tx_pending );
3923+ sys_slist_init (& ag -> tx_submit_pending );
38603924
38613925 k_sem_init (& ag -> lock , 1 , 1 );
38623926
@@ -4053,6 +4117,13 @@ static void hfp_ag_init(void)
40534117 bt_sdp_register_service (& hfp_ag_rec );
40544118
40554119 bt_sco_conn_cb_register (& ag_sco_conn_cb );
4120+
4121+ k_fifo_init (& ag_tx_free );
4122+ k_fifo_init (& ag_tx_notify );
4123+
4124+ ARRAY_FOR_EACH (ag_tx , index ) {
4125+ k_fifo_put (& ag_tx_free , & ag_tx [index ]);
4126+ }
40564127}
40574128
40584129int bt_hfp_ag_register (struct bt_hfp_ag_cb * cb )
0 commit comments