@@ -1016,77 +1016,28 @@ static int bt_hfp_ag_bac_handler(struct bt_hfp_ag *ag, struct net_buf *buf)
10161016 return 0 ;
10171017}
10181018
1019- static void bt_hfp_ag_get_ongoing_calls (struct bt_hfp_ag * ag )
1019+ static int bt_hfp_ag_get_ongoing_calls (struct bt_hfp_ag * ag )
10201020{
1021- struct bt_hfp_ag_ongoing_call * call ;
10221021 int err ;
1023- bool valid ;
1024- size_t len ;
10251022
10261023 ag -> ongoing_call_count = 0 ;
10271024
10281025 if ((bt_ag == NULL ) || (bt_ag -> get_ongoing_call == NULL )) {
10291026 LOG_DBG ("No ongoing call retrieval method available" );
1030- return ;
1027+ return - EINVAL ;
10311028 }
10321029
1033- do {
1034- call = & ag -> ongoing_calls [ag -> ongoing_call_count ];
1035- memset (call , 0 , sizeof (* call ));
1036-
1037- valid = true;
1038-
1039- err = bt_ag -> get_ongoing_call (ag , call );
1040- if (err != 0 ) {
1041- LOG_DBG ("No ongoing call retrieved" );
1042- break ;
1043- }
1044-
1045- len = strlen (call -> number );
1046- if ((len == 0 ) || (len >= ARRAY_SIZE (call -> number ))) {
1047- LOG_WRN ("Invalid call number" );
1048- break ;
1049- }
1050-
1051- switch (call -> status ) {
1052- case BT_HFP_AG_CALL_STATUS_DIALING :
1053- case BT_HFP_AG_CALL_STATUS_ALERTING :
1054- if (call -> dir == BT_HFP_AG_CALL_DIR_INCOMING ) {
1055- LOG_ERR ("Dialing call cannot be incoming" );
1056- valid = false;
1057- }
1058- break ;
1059- case BT_HFP_AG_CALL_STATUS_INCOMING :
1060- case BT_HFP_AG_CALL_STATUS_WAITING :
1061- case BT_HFP_AG_CALL_STATUS_INCOMING_HELD :
1062- if (call -> dir == BT_HFP_AG_CALL_DIR_OUTGOING ) {
1063- LOG_ERR ("Incoming call cannot be outgoing" );
1064- valid = false;
1065- }
1066- break ;
1067- default :
1068- break ;
1069- }
1070-
1071- if (!valid ) {
1072- continue ;
1073- }
1074-
1075- ag -> ongoing_call_count ++ ;
1076- } while (ag -> ongoing_call_count < ARRAY_SIZE (ag -> ongoing_calls ));
1030+ if (ag -> state == BT_HFP_CONNECTED ) {
1031+ LOG_ERR ("Only works during SLC establishment phase" );
1032+ return - EINVAL ;
1033+ }
10771034
1078- if (ag -> ongoing_call_count > 1 ) {
1079- switch (ag -> ongoing_calls [0 ].status ) {
1080- case BT_HFP_AG_CALL_STATUS_ACTIVE :
1081- case BT_HFP_AG_CALL_STATUS_HELD :
1082- case BT_HFP_AG_CALL_STATUS_INCOMING_HELD :
1083- break ;
1084- default :
1085- LOG_ERR ("Unexpected call status for multiple calls" );
1086- ag -> ongoing_call_count = 1 ;
1087- break ;
1088- }
1035+ err = bt_ag -> get_ongoing_call (ag );
1036+ if (err != 0 ) {
1037+ LOG_DBG ("No ongoing call retrieved" );
10891038 }
1039+
1040+ return err ;
10901041}
10911042
10921043static int bt_hfp_ag_notify_cind_value (struct bt_hfp_ag * ag )
@@ -1195,10 +1146,16 @@ static int bt_hfp_ag_cind_handler(struct bt_hfp_ag *ag, struct net_buf *buf)
11951146 ag_ind [BT_HFP_AG_ROAM_IND ].max , ag_ind [BT_HFP_AG_BATTERY_IND ].name ,
11961147 ag_ind [BT_HFP_AG_BATTERY_IND ].min , ag_ind [BT_HFP_AG_BATTERY_IND ].connector ,
11971148 ag_ind [BT_HFP_AG_BATTERY_IND ].max );
1198-
1199- bt_hfp_ag_get_ongoing_calls (ag );
12001149 } else {
1201- err = bt_hfp_ag_notify_cind_value (ag );
1150+ err = bt_hfp_ag_get_ongoing_calls (ag );
1151+ if (err != 0 ) {
1152+ err = bt_hfp_ag_notify_cind_value (ag );
1153+ } else {
1154+ err = - EINPROGRESS ;
1155+ atomic_set_bit (ag -> flags , BT_HGP_AG_ONGOING_CALLS );
1156+ k_work_reschedule (& ag -> ongoing_call_work ,
1157+ K_MSEC (CONFIG_BT_HFP_AG_GET_ONGOING_CALL_TIMEOUT ));
1158+ }
12021159 }
12031160
12041161 return err ;
@@ -3534,6 +3491,11 @@ static void hfp_ag_recv(struct bt_rfcomm_dlc *dlc, struct net_buf *buf)
35343491 }
35353492 }
35363493
3494+ if (err == - EINPROGRESS ) {
3495+ LOG_DBG ("OK code will be replied later" );
3496+ return ;
3497+ }
3498+
35373499 if ((err != 0 ) && atomic_test_bit (ag -> flags , BT_HFP_AG_CMEE_ENABLE )) {
35383500 cme_err = bt_hfp_ag_get_cme_err (err );
35393501 err = hfp_ag_send_data (ag , NULL , NULL , "\r\n+CME ERROR:%d\r\n" , (uint32_t )cme_err );
@@ -3784,6 +3746,29 @@ static void bt_ag_ringing_work(struct k_work *work)
37843746 (void )hfp_ag_next_step (call -> ag , bt_ag_ringing_work_cb , call );
37853747}
37863748
3749+ static void bt_ag_send_ok_code (struct bt_hfp_ag * ag )
3750+ {
3751+ if (hfp_ag_send_data (ag , NULL , NULL , "\r\nOK\r\n" ) != 0 ) {
3752+ LOG_ERR ("Failed to send OK code" );
3753+ }
3754+ }
3755+
3756+ static void bt_ag_ongoing_call_work (struct k_work * work )
3757+ {
3758+ struct k_work_delayable * dwork = k_work_delayable_from_work (work );
3759+ struct bt_hfp_ag * ag = CONTAINER_OF (dwork , struct bt_hfp_ag , ongoing_call_work );
3760+
3761+ LOG_DBG ("" );
3762+
3763+ if (!atomic_test_and_clear_bit (ag -> flags , BT_HGP_AG_ONGOING_CALLS )) {
3764+ return ;
3765+ }
3766+
3767+ ag -> ongoing_call_count = 0 ;
3768+ bt_hfp_ag_notify_cind_value (ag );
3769+ bt_ag_send_ok_code (ag );
3770+ }
3771+
37873772static K_KERNEL_STACK_MEMBER (ag_thread_stack , CONFIG_BT_HFP_AG_THREAD_STACK_SIZE ) ;
37883773
37893774static struct bt_hfp_ag * hfp_ag_create (struct bt_conn * conn )
@@ -3881,6 +3866,8 @@ static struct bt_hfp_ag *hfp_ag_create(struct bt_conn *conn)
38813866
38823867 /* Init delay work */
38833868 k_work_init_delayable (& ag -> tx_work , bt_ag_tx_work );
3869+ /* Init delay work */
3870+ k_work_init_delayable (& ag -> ongoing_call_work , bt_ag_ongoing_call_work );
38843871
38853872 return ag ;
38863873}
@@ -5204,3 +5191,94 @@ int bt_hfp_ag_hf_indicator(struct bt_hfp_ag *ag, enum hfp_ag_hf_indicators indic
52045191 return - ENOTSUP ;
52055192#endif /* CONFIG_BT_HFP_HF_HF_INDICATORS */
52065193}
5194+
5195+ int bt_hfp_ag_ongoing_calls (struct bt_hfp_ag * ag , struct bt_hfp_ag_ongoing_call * calls ,
5196+ size_t count )
5197+ {
5198+ struct bt_hfp_ag_ongoing_call * call ;
5199+ bool valid ;
5200+ size_t len ;
5201+ int err = - EINVAL ;
5202+
5203+ LOG_DBG ("" );
5204+
5205+ if (ag == NULL ) {
5206+ return - EINVAL ;
5207+ }
5208+
5209+ if (count > ARRAY_SIZE (ag -> ongoing_calls )) {
5210+ LOG_ERR ("Out of buffer (%u > %u)" , count , ARRAY_SIZE (ag -> ongoing_calls ));
5211+ return - ENOMEM ;
5212+ }
5213+
5214+ if (!atomic_test_and_clear_bit (ag -> flags , BT_HGP_AG_ONGOING_CALLS )) {
5215+ LOG_ERR ("Cannot set ongoing calls" );
5216+ return - ESRCH ;
5217+ }
5218+
5219+ for (ag -> ongoing_call_count = 0 ; ag -> ongoing_call_count < count ; ag -> ongoing_call_count ++ ) {
5220+ call = & calls [ag -> ongoing_call_count ];
5221+ valid = true;
5222+
5223+ len = strlen (call -> number );
5224+ if ((len == 0 ) || (len >= ARRAY_SIZE (call -> number ))) {
5225+ LOG_WRN ("Invalid call number" );
5226+ /* Clear all calls */
5227+ ag -> ongoing_call_count = 0 ;
5228+ goto failed ;
5229+ }
5230+
5231+ switch (call -> status ) {
5232+ case BT_HFP_AG_CALL_STATUS_DIALING :
5233+ case BT_HFP_AG_CALL_STATUS_ALERTING :
5234+ if (call -> dir == BT_HFP_AG_CALL_DIR_INCOMING ) {
5235+ LOG_ERR ("Dialing call cannot be incoming" );
5236+ valid = false;
5237+ }
5238+ break ;
5239+ case BT_HFP_AG_CALL_STATUS_INCOMING :
5240+ case BT_HFP_AG_CALL_STATUS_WAITING :
5241+ case BT_HFP_AG_CALL_STATUS_INCOMING_HELD :
5242+ if (call -> dir == BT_HFP_AG_CALL_DIR_OUTGOING ) {
5243+ LOG_ERR ("Incoming call cannot be outgoing" );
5244+ valid = false;
5245+ }
5246+ break ;
5247+ default :
5248+ LOG_ERR ("Invalid status" );
5249+ valid = false;
5250+ break ;
5251+ }
5252+
5253+ if (!valid ) {
5254+ /* Clear all calls */
5255+ ag -> ongoing_call_count = 0 ;
5256+ goto failed ;
5257+ }
5258+
5259+ memcpy (& ag -> ongoing_calls [ag -> ongoing_call_count ], call ,
5260+ sizeof (ag -> ongoing_calls [ag -> ongoing_call_count ]));
5261+ }
5262+
5263+ if (ag -> ongoing_call_count > 1 ) {
5264+ switch (ag -> ongoing_calls [0 ].status ) {
5265+ case BT_HFP_AG_CALL_STATUS_ACTIVE :
5266+ case BT_HFP_AG_CALL_STATUS_HELD :
5267+ case BT_HFP_AG_CALL_STATUS_INCOMING_HELD :
5268+ break ;
5269+ default :
5270+ LOG_ERR ("Unexpected call status for multiple calls" );
5271+ /* Clear all calls */
5272+ ag -> ongoing_call_count = 0 ;
5273+ goto failed ;
5274+ }
5275+ }
5276+
5277+ err = 0 ;
5278+
5279+ failed :
5280+ k_work_cancel_delayable (& ag -> ongoing_call_work );
5281+ bt_hfp_ag_notify_cind_value (ag );
5282+ bt_ag_send_ok_code (ag );
5283+ return err ;
5284+ }
0 commit comments