xref: /btstack/src/classic/hfp_gsm_model.c (revision f3e773c5646eef8d78872f4b31ac4d3a4725dbb7)
174386ee0SMatthias Ringwald /*
274386ee0SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
374386ee0SMatthias Ringwald  *
474386ee0SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
574386ee0SMatthias Ringwald  * modification, are permitted provided that the following conditions
674386ee0SMatthias Ringwald  * are met:
774386ee0SMatthias Ringwald  *
874386ee0SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
974386ee0SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
1074386ee0SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
1174386ee0SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
1274386ee0SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
1374386ee0SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
1474386ee0SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
1574386ee0SMatthias Ringwald  *    from this software without specific prior written permission.
1674386ee0SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
1774386ee0SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
1874386ee0SMatthias Ringwald  *    monetary gain.
1974386ee0SMatthias Ringwald  *
2074386ee0SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
2174386ee0SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2274386ee0SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
232fca4dadSMilanka Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
242fca4dadSMilanka Ringwald  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2574386ee0SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2674386ee0SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
2774386ee0SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2874386ee0SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2974386ee0SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
3074386ee0SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3174386ee0SMatthias Ringwald  * SUCH DAMAGE.
3274386ee0SMatthias Ringwald  *
3374386ee0SMatthias Ringwald  * Please inquire about commercial licensing options at
3474386ee0SMatthias Ringwald  * [email protected]
3574386ee0SMatthias Ringwald  *
3674386ee0SMatthias Ringwald  */
37ab2c6ae4SMatthias Ringwald 
38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "hfp_gsm_model.c"
3974386ee0SMatthias Ringwald 
4074386ee0SMatthias Ringwald // *****************************************************************************
4174386ee0SMatthias Ringwald //
429cae807eSMatthias Ringwald // GSM Model
4374386ee0SMatthias Ringwald //
4474386ee0SMatthias Ringwald // *****************************************************************************
4574386ee0SMatthias Ringwald 
467907f069SMatthias Ringwald #include "btstack_config.h"
4774386ee0SMatthias Ringwald 
4874386ee0SMatthias Ringwald #include <stdint.h>
4974386ee0SMatthias Ringwald #include <string.h>
5074386ee0SMatthias Ringwald 
5174386ee0SMatthias Ringwald #include "btstack_memory.h"
5259c6af15SMatthias Ringwald #include "classic/core.h"
5374386ee0SMatthias Ringwald #include "classic/hfp.h"
5474386ee0SMatthias Ringwald #include "classic/hfp_gsm_model.h"
55746ccb7eSMatthias Ringwald #include "classic/sdp_server.h"
56efda0b48SMatthias Ringwald #include "classic/sdp_client_rfcomm.h"
5716ece135SMatthias Ringwald #include "btstack_debug.h"
5874386ee0SMatthias Ringwald #include "hci.h"
5956042629SMatthias Ringwald #include "hci_cmd.h"
6074386ee0SMatthias Ringwald #include "hci_dump.h"
6174386ee0SMatthias Ringwald #include "l2cap.h"
6282636622SMatthias Ringwald #include "btstack_run_loop.h"
6374386ee0SMatthias Ringwald 
6474386ee0SMatthias Ringwald #define HFP_GSM_MAX_NR_CALLS 3
659cae807eSMatthias Ringwald #define HFP_GSM_MAX_CALL_NUMBER_SIZE 25
6674386ee0SMatthias Ringwald 
67aeb0f0feSMatthias Ringwald static hfp_gsm_call_t         hfp_gsm_model_calls[HFP_GSM_MAX_NR_CALLS];
68aeb0f0feSMatthias Ringwald static hfp_callsetup_status_t hfp_gsm_model_callsetup_status;
6974386ee0SMatthias Ringwald 
70aeb0f0feSMatthias Ringwald static uint8_t hfp_gsm_model_clip_type;
71aeb0f0feSMatthias Ringwald static char    hfp_gsm_model_clip_number[HFP_GSM_MAX_CALL_NUMBER_SIZE];
72aeb0f0feSMatthias Ringwald static char    hfp_gsm_model_last_dialed_number[HFP_GSM_MAX_CALL_NUMBER_SIZE];
73d0c20769SMatthias Ringwald 
74aeb0f0feSMatthias Ringwald static inline int hfp_gsm_model_get_number_active_calls(void);
7566a048abSMatthias Ringwald 
set_callsetup_status(hfp_callsetup_status_t status)7666a048abSMatthias Ringwald static void set_callsetup_status(hfp_callsetup_status_t status){
77aeb0f0feSMatthias Ringwald     hfp_gsm_model_callsetup_status = status;
78aeb0f0feSMatthias Ringwald     if (hfp_gsm_model_callsetup_status != HFP_CALLSETUP_STATUS_OUTGOING_CALL_SETUP_IN_ALERTING_STATE) return;
7966a048abSMatthias Ringwald 
8066a048abSMatthias Ringwald     int i ;
8166a048abSMatthias Ringwald     for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
82aeb0f0feSMatthias Ringwald         if (hfp_gsm_model_calls[i].direction == HFP_ENHANCED_CALL_DIR_OUTGOING){
83aeb0f0feSMatthias Ringwald             hfp_gsm_model_calls[i].enhanced_status = HFP_ENHANCED_CALL_STATUS_OUTGOING_ALERTING;
8466a048abSMatthias Ringwald         }
8566a048abSMatthias Ringwald     }
8666a048abSMatthias Ringwald }
8766a048abSMatthias Ringwald 
set_enhanced_call_status_active(int index_in_table)8866a048abSMatthias Ringwald static inline void set_enhanced_call_status_active(int index_in_table){
893e11d175SMatthias Ringwald     if ((index_in_table < 0) || (index_in_table >= HFP_GSM_MAX_NR_CALLS)) return;
90aeb0f0feSMatthias Ringwald     hfp_gsm_model_calls[index_in_table].enhanced_status = HFP_ENHANCED_CALL_STATUS_ACTIVE;
91df1e871fSMatthias Ringwald     hfp_gsm_model_calls[index_in_table].used_slot = true;
9266a048abSMatthias Ringwald }
9366a048abSMatthias Ringwald 
set_enhanced_call_status_held(int index_in_table)9466a048abSMatthias Ringwald static inline void set_enhanced_call_status_held(int index_in_table){
953e11d175SMatthias Ringwald     if ((index_in_table < 0) || (index_in_table >= HFP_GSM_MAX_NR_CALLS)) return;
96aeb0f0feSMatthias Ringwald     hfp_gsm_model_calls[index_in_table].enhanced_status = HFP_ENHANCED_CALL_STATUS_HELD;
97df1e871fSMatthias Ringwald     hfp_gsm_model_calls[index_in_table].used_slot = true;
9866a048abSMatthias Ringwald }
9966a048abSMatthias Ringwald 
set_enhanced_call_status_response_hold(int index_in_table)10066a048abSMatthias Ringwald static inline void set_enhanced_call_status_response_hold(int index_in_table){
1013e11d175SMatthias Ringwald     if ((index_in_table < 0) || (index_in_table >= HFP_GSM_MAX_NR_CALLS)) return;
102aeb0f0feSMatthias Ringwald     hfp_gsm_model_calls[index_in_table].enhanced_status = HFP_ENHANCED_CALL_STATUS_CALL_HELD_BY_RESPONSE_AND_HOLD;
103df1e871fSMatthias Ringwald     hfp_gsm_model_calls[index_in_table].used_slot = true;
10466a048abSMatthias Ringwald }
10566a048abSMatthias Ringwald 
set_enhanced_call_status_initiated(int index_in_table)10666a048abSMatthias Ringwald static inline void set_enhanced_call_status_initiated(int index_in_table){
1073e11d175SMatthias Ringwald     if ((index_in_table < 0) || (index_in_table >= HFP_GSM_MAX_NR_CALLS)) return;
108aeb0f0feSMatthias Ringwald     if (hfp_gsm_model_calls[index_in_table].direction == HFP_ENHANCED_CALL_DIR_OUTGOING){
109aeb0f0feSMatthias Ringwald         hfp_gsm_model_calls[index_in_table].enhanced_status = HFP_ENHANCED_CALL_STATUS_OUTGOING_DIALING;
11066a048abSMatthias Ringwald     } else {
111aeb0f0feSMatthias Ringwald         if (hfp_gsm_model_get_number_active_calls() > 0){
112aeb0f0feSMatthias Ringwald             hfp_gsm_model_calls[index_in_table].enhanced_status = HFP_ENHANCED_CALL_STATUS_INCOMING_WAITING;
11366a048abSMatthias Ringwald         } else {
114aeb0f0feSMatthias Ringwald             hfp_gsm_model_calls[index_in_table].enhanced_status = HFP_ENHANCED_CALL_STATUS_INCOMING;
11566a048abSMatthias Ringwald         }
11666a048abSMatthias Ringwald     }
117df1e871fSMatthias Ringwald     hfp_gsm_model_calls[index_in_table].used_slot = true;
11866a048abSMatthias Ringwald }
11966a048abSMatthias Ringwald 
get_enhanced_call_status(int index_in_table)12066a048abSMatthias Ringwald static int get_enhanced_call_status(int index_in_table){
1213e11d175SMatthias Ringwald     if ((index_in_table < 0) || (index_in_table >= HFP_GSM_MAX_NR_CALLS)) return -1;
122aeb0f0feSMatthias Ringwald     if (!hfp_gsm_model_calls[index_in_table].used_slot) return -1;
123aeb0f0feSMatthias Ringwald     return hfp_gsm_model_calls[index_in_table].enhanced_status;
12466a048abSMatthias Ringwald }
12566a048abSMatthias Ringwald 
is_enhanced_call_status_active(int index_in_table)12666a048abSMatthias Ringwald static inline int is_enhanced_call_status_active(int index_in_table){
1273e11d175SMatthias Ringwald     if ((index_in_table < 0) || (index_in_table >= HFP_GSM_MAX_NR_CALLS)) return 0;
12866a048abSMatthias Ringwald     return get_enhanced_call_status(index_in_table) == HFP_ENHANCED_CALL_STATUS_ACTIVE;
12966a048abSMatthias Ringwald }
13066a048abSMatthias Ringwald 
is_enhanced_call_status_initiated(int index_in_table)13166a048abSMatthias Ringwald static inline int is_enhanced_call_status_initiated(int index_in_table){
1323e11d175SMatthias Ringwald     if ((index_in_table < 0) || (index_in_table >= HFP_GSM_MAX_NR_CALLS)) return 0;
13366a048abSMatthias Ringwald     switch (get_enhanced_call_status(index_in_table)){
13466a048abSMatthias Ringwald         case HFP_ENHANCED_CALL_STATUS_OUTGOING_DIALING:
13566a048abSMatthias Ringwald         case HFP_ENHANCED_CALL_STATUS_OUTGOING_ALERTING:
13666a048abSMatthias Ringwald         case HFP_ENHANCED_CALL_STATUS_INCOMING:
13766a048abSMatthias Ringwald         case HFP_ENHANCED_CALL_STATUS_INCOMING_WAITING:
13866a048abSMatthias Ringwald             return 1;
13966a048abSMatthias Ringwald         default:
14066a048abSMatthias Ringwald             return 0;
14166a048abSMatthias Ringwald     }
14266a048abSMatthias Ringwald }
14366a048abSMatthias Ringwald 
free_call_slot(int index_in_table)14466a048abSMatthias Ringwald static void free_call_slot(int index_in_table){
1453e11d175SMatthias Ringwald     if ((index_in_table < 0) || (index_in_table >= HFP_GSM_MAX_NR_CALLS)) return;
146df1e871fSMatthias Ringwald     hfp_gsm_model_calls[index_in_table].used_slot = false;
14766a048abSMatthias Ringwald }
148d0c20769SMatthias Ringwald 
hfp_gsm_init(void)149d210d9c4SMatthias Ringwald void hfp_gsm_init(void){
150aeb0f0feSMatthias Ringwald     hfp_gsm_model_callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS;
151aeb0f0feSMatthias Ringwald     hfp_gsm_model_clip_type = 0;
152aeb0f0feSMatthias Ringwald     memset(hfp_gsm_model_clip_number, 0, sizeof(hfp_gsm_model_clip_number));
153aeb0f0feSMatthias Ringwald     memset(hfp_gsm_model_last_dialed_number, 0, sizeof(hfp_gsm_model_last_dialed_number));
154aeb0f0feSMatthias Ringwald     memset(hfp_gsm_model_calls, 0, sizeof(hfp_gsm_model_calls));
155d210d9c4SMatthias Ringwald     int i;
156d210d9c4SMatthias Ringwald     for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
15766a048abSMatthias Ringwald         free_call_slot(i);
158d210d9c4SMatthias Ringwald     }
159d210d9c4SMatthias Ringwald }
16074386ee0SMatthias Ringwald 
hfp_gsm_deinit(void)16120b2edb6SMatthias Ringwald void hfp_gsm_deinit(void){
162aeb0f0feSMatthias Ringwald     (void) memset(hfp_gsm_model_calls, 0, sizeof(hfp_gsm_model_calls));
163aeb0f0feSMatthias Ringwald     hfp_gsm_model_callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS;
164aeb0f0feSMatthias Ringwald     hfp_gsm_model_clip_type = 0;
165aeb0f0feSMatthias Ringwald     (void) memset(hfp_gsm_model_clip_number, 0, sizeof(hfp_gsm_model_clip_number));
166aeb0f0feSMatthias Ringwald     (void) memset(hfp_gsm_model_last_dialed_number, 0, sizeof(hfp_gsm_model_last_dialed_number));
16720b2edb6SMatthias Ringwald }
16820b2edb6SMatthias Ringwald 
get_number_calls_with_enhanced_status(hfp_enhanced_call_status_t enhanced_status)16966a048abSMatthias Ringwald static int get_number_calls_with_enhanced_status(hfp_enhanced_call_status_t enhanced_status){
17074386ee0SMatthias Ringwald     int i, count = 0;
17174386ee0SMatthias Ringwald     for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
172fdfcab43SMatthias Ringwald         if (get_enhanced_call_status(i) == (int) enhanced_status) count++;
17374386ee0SMatthias Ringwald     }
17474386ee0SMatthias Ringwald     return count;
17574386ee0SMatthias Ringwald }
17674386ee0SMatthias Ringwald 
get_call_index_with_enhanced_status(hfp_enhanced_call_status_t enhanced_status)17766a048abSMatthias Ringwald static int get_call_index_with_enhanced_status(hfp_enhanced_call_status_t enhanced_status){
17874386ee0SMatthias Ringwald     int i ;
17974386ee0SMatthias Ringwald     for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
180fdfcab43SMatthias Ringwald         if (get_enhanced_call_status(i) == (int) enhanced_status) return i;
18166a048abSMatthias Ringwald     }
18266a048abSMatthias Ringwald     return -1;
18366a048abSMatthias Ringwald }
18466a048abSMatthias Ringwald 
get_initiated_call_index(void)18566a048abSMatthias Ringwald static inline int get_initiated_call_index(void){
18666a048abSMatthias Ringwald     int i ;
18766a048abSMatthias Ringwald     for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
18866a048abSMatthias Ringwald         if (is_enhanced_call_status_initiated(i)) return i;
18974386ee0SMatthias Ringwald     }
19074386ee0SMatthias Ringwald     return -1;
19174386ee0SMatthias Ringwald }
19274386ee0SMatthias Ringwald 
get_next_free_slot(void)1939cae807eSMatthias Ringwald static inline int get_next_free_slot(void){
19466a048abSMatthias Ringwald     int i ;
19566a048abSMatthias Ringwald     for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
196aeb0f0feSMatthias Ringwald         if (!hfp_gsm_model_calls[i].used_slot) return i;
19766a048abSMatthias Ringwald     }
19866a048abSMatthias Ringwald     return -1;
19974386ee0SMatthias Ringwald }
20074386ee0SMatthias Ringwald 
get_active_call_index(void)2019cae807eSMatthias Ringwald static inline int get_active_call_index(void){
20266a048abSMatthias Ringwald     return get_call_index_with_enhanced_status(HFP_ENHANCED_CALL_STATUS_ACTIVE);
203d210d9c4SMatthias Ringwald }
204d210d9c4SMatthias Ringwald 
get_dialing_call_index(void)205baa221a8SMilanka Ringwald static inline int get_dialing_call_index(void){
206baa221a8SMilanka Ringwald     return get_call_index_with_enhanced_status(HFP_ENHANCED_CALL_STATUS_OUTGOING_DIALING);
207baa221a8SMilanka Ringwald }
208baa221a8SMilanka Ringwald 
get_held_call_index(void)2099cae807eSMatthias Ringwald static inline int get_held_call_index(void){
21066a048abSMatthias Ringwald     return get_call_index_with_enhanced_status(HFP_ENHANCED_CALL_STATUS_HELD);
211d210d9c4SMatthias Ringwald }
212d210d9c4SMatthias Ringwald 
get_response_held_call_index(void)2139cae807eSMatthias Ringwald static inline int get_response_held_call_index(void){
21466a048abSMatthias Ringwald     return get_call_index_with_enhanced_status(HFP_ENHANCED_CALL_STATUS_CALL_HELD_BY_RESPONSE_AND_HOLD);
215d210d9c4SMatthias Ringwald }
216d210d9c4SMatthias Ringwald 
get_number_none_calls(void)2179cae807eSMatthias Ringwald static inline int get_number_none_calls(void){
21866a048abSMatthias Ringwald     int i, count = 0;
21966a048abSMatthias Ringwald     for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
220aeb0f0feSMatthias Ringwald         if (!hfp_gsm_model_calls[i].used_slot) count++;
22166a048abSMatthias Ringwald     }
22266a048abSMatthias Ringwald     return count;
223d210d9c4SMatthias Ringwald }
22474386ee0SMatthias Ringwald 
hfp_gsm_model_get_number_active_calls(void)225aeb0f0feSMatthias Ringwald static inline int hfp_gsm_model_get_number_active_calls(void){
22666a048abSMatthias Ringwald     return get_number_calls_with_enhanced_status(HFP_ENHANCED_CALL_STATUS_ACTIVE);
22774386ee0SMatthias Ringwald }
22874386ee0SMatthias Ringwald 
get_number_held_calls(void)2299cae807eSMatthias Ringwald static inline int get_number_held_calls(void){
23066a048abSMatthias Ringwald     return get_number_calls_with_enhanced_status(HFP_ENHANCED_CALL_STATUS_HELD);
23174386ee0SMatthias Ringwald }
23274386ee0SMatthias Ringwald 
get_number_response_held_calls(void)2339cae807eSMatthias Ringwald static inline int get_number_response_held_calls(void){
23466a048abSMatthias Ringwald     return get_number_calls_with_enhanced_status(HFP_ENHANCED_CALL_STATUS_CALL_HELD_BY_RESPONSE_AND_HOLD);
235d210d9c4SMatthias Ringwald }
236d210d9c4SMatthias Ringwald 
next_call_index(void)2379cae807eSMatthias Ringwald static int next_call_index(void){
238d0c20769SMatthias Ringwald     return HFP_GSM_MAX_NR_CALLS + 1 - get_number_none_calls();
239d0c20769SMatthias Ringwald }
240d0c20769SMatthias Ringwald 
hfp_gsm_set_clip(int index_in_table,uint8_t type,const char * number)241d0c20769SMatthias Ringwald static void hfp_gsm_set_clip(int index_in_table, uint8_t type, const char * number){
24221791470SMilanka Ringwald     uint16_t number_str_len = (uint16_t) strlen(number);
24321791470SMilanka Ringwald     if (number_str_len == 0) return;
2449cae807eSMatthias Ringwald 
245aeb0f0feSMatthias Ringwald     hfp_gsm_model_calls[index_in_table].clip_type = type;
246c10fde09SMatthias Ringwald     btstack_strcpy(hfp_gsm_model_calls[index_in_table].clip_number, HFP_GSM_MAX_CALL_NUMBER_SIZE, number);
247c10fde09SMatthias Ringwald     btstack_strcpy(hfp_gsm_model_last_dialed_number, HFP_GSM_MAX_CALL_NUMBER_SIZE, number);
248aeb0f0feSMatthias Ringwald     hfp_gsm_model_clip_type = 0;
249aeb0f0feSMatthias Ringwald     memset(hfp_gsm_model_clip_number, 0, sizeof(hfp_gsm_model_clip_number));
250d0c20769SMatthias Ringwald }
251d0c20769SMatthias Ringwald 
delete_call(int delete_index_in_table)252d0c20769SMatthias Ringwald static void delete_call(int delete_index_in_table){
253d0c20769SMatthias Ringwald     int i ;
254d0c20769SMatthias Ringwald     for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
255aeb0f0feSMatthias Ringwald         if (hfp_gsm_model_calls[i].index > hfp_gsm_model_calls[delete_index_in_table].index){
256aeb0f0feSMatthias Ringwald             hfp_gsm_model_calls[i].index--;
257d0c20769SMatthias Ringwald         }
258d0c20769SMatthias Ringwald     }
25966a048abSMatthias Ringwald     free_call_slot(delete_index_in_table);
260d0c20769SMatthias Ringwald 
261aeb0f0feSMatthias Ringwald     hfp_gsm_model_calls[delete_index_in_table].clip_type = 0;
262aeb0f0feSMatthias Ringwald     hfp_gsm_model_calls[delete_index_in_table].index = 0;
263aeb0f0feSMatthias Ringwald     hfp_gsm_model_calls[delete_index_in_table].clip_number[0] = '\0';
264aeb0f0feSMatthias Ringwald     hfp_gsm_model_calls[delete_index_in_table].mpty = HFP_ENHANCED_CALL_MPTY_NOT_A_CONFERENCE_CALL;
265d0c20769SMatthias Ringwald }
266d0c20769SMatthias Ringwald 
2679cae807eSMatthias Ringwald 
create_call(hfp_enhanced_call_dir_t direction)2689cae807eSMatthias Ringwald static void create_call(hfp_enhanced_call_dir_t direction){
269d0c20769SMatthias Ringwald     int next_free_slot = get_next_free_slot();
270d7089767SMatthias Ringwald     btstack_assert(next_free_slot >= 0);
271aeb0f0feSMatthias Ringwald     hfp_gsm_model_calls[next_free_slot].direction = direction;
272aeb0f0feSMatthias Ringwald     hfp_gsm_model_calls[next_free_slot].index = next_call_index();
27366a048abSMatthias Ringwald     set_enhanced_call_status_initiated(next_free_slot);
274aeb0f0feSMatthias Ringwald     hfp_gsm_model_calls[next_free_slot].clip_type = 0;
275aeb0f0feSMatthias Ringwald     hfp_gsm_model_calls[next_free_slot].clip_number[0] = '\0';
276aeb0f0feSMatthias Ringwald     hfp_gsm_model_calls[next_free_slot].mpty = HFP_ENHANCED_CALL_MPTY_NOT_A_CONFERENCE_CALL;
277d0c20769SMatthias Ringwald 
278aeb0f0feSMatthias Ringwald     hfp_gsm_set_clip(next_free_slot, hfp_gsm_model_clip_type, hfp_gsm_model_clip_number);
279d0c20769SMatthias Ringwald }
280d0c20769SMatthias Ringwald 
2819cae807eSMatthias Ringwald 
hfp_gsm_get_number_of_calls(void)2829cae807eSMatthias Ringwald int hfp_gsm_get_number_of_calls(void){
2839cae807eSMatthias Ringwald     return HFP_GSM_MAX_NR_CALLS - get_number_none_calls();
2849cae807eSMatthias Ringwald }
2859cae807eSMatthias Ringwald 
hfp_gsm_clear_last_dialed_number(void)2869cae807eSMatthias Ringwald void hfp_gsm_clear_last_dialed_number(void){
287aeb0f0feSMatthias Ringwald     memset(hfp_gsm_model_last_dialed_number, 0, sizeof(hfp_gsm_model_last_dialed_number));
2889cae807eSMatthias Ringwald }
2899cae807eSMatthias Ringwald 
hfp_gsm_last_dialed_number(void)2909cae807eSMatthias Ringwald char * hfp_gsm_last_dialed_number(void){
291aeb0f0feSMatthias Ringwald     return &hfp_gsm_model_last_dialed_number[0];
2929cae807eSMatthias Ringwald }
2939cae807eSMatthias Ringwald 
hfp_gsm_set_last_dialed_number(const char * number)2949de679b7SMilanka Ringwald void hfp_gsm_set_last_dialed_number(const char* number){
295c10fde09SMatthias Ringwald     btstack_strcpy(hfp_gsm_model_last_dialed_number, sizeof(hfp_gsm_model_last_dialed_number), number);
2969de679b7SMilanka Ringwald }
2979de679b7SMilanka Ringwald 
hfp_gsm_call(int call_index)2989cae807eSMatthias Ringwald hfp_gsm_call_t * hfp_gsm_call(int call_index){
2999cae807eSMatthias Ringwald     int i;
3009cae807eSMatthias Ringwald 
3019cae807eSMatthias Ringwald     for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
302aeb0f0feSMatthias Ringwald         hfp_gsm_call_t * call = &hfp_gsm_model_calls[i];
3039cae807eSMatthias Ringwald         if (call->index != call_index) continue;
3049cae807eSMatthias Ringwald         return call;
3059cae807eSMatthias Ringwald     }
3069cae807eSMatthias Ringwald     return NULL;
3079cae807eSMatthias Ringwald }
3089cae807eSMatthias Ringwald 
hfp_gsm_clip_type(void)3099cae807eSMatthias Ringwald uint8_t hfp_gsm_clip_type(void){
310aeb0f0feSMatthias Ringwald     if (hfp_gsm_model_clip_type != 0) return hfp_gsm_model_clip_type;
311d0c20769SMatthias Ringwald 
312d0c20769SMatthias Ringwald     int initiated_call_index = get_initiated_call_index();
313d0c20769SMatthias Ringwald     if (initiated_call_index != -1){
314aeb0f0feSMatthias Ringwald         if (hfp_gsm_model_calls[initiated_call_index].clip_type != 0) {
315aeb0f0feSMatthias Ringwald             return hfp_gsm_model_calls[initiated_call_index].clip_type;
316d0c20769SMatthias Ringwald         }
317d0c20769SMatthias Ringwald     }
318d0c20769SMatthias Ringwald 
319d0c20769SMatthias Ringwald     int active_call_index = get_active_call_index();
320d0c20769SMatthias Ringwald     if (active_call_index != -1){
321aeb0f0feSMatthias Ringwald         if (hfp_gsm_model_calls[active_call_index].clip_type != 0) {
322aeb0f0feSMatthias Ringwald             return hfp_gsm_model_calls[active_call_index].clip_type;
323d0c20769SMatthias Ringwald         }
324d0c20769SMatthias Ringwald     }
325d0c20769SMatthias Ringwald     return 0;
326d0c20769SMatthias Ringwald }
327d0c20769SMatthias Ringwald 
hfp_gsm_clip_number(void)3289cae807eSMatthias Ringwald char *  hfp_gsm_clip_number(void){
329aeb0f0feSMatthias Ringwald     if (strlen(hfp_gsm_model_clip_number) != 0) return hfp_gsm_model_clip_number;
330d0c20769SMatthias Ringwald 
331d0c20769SMatthias Ringwald     int initiated_call_index = get_initiated_call_index();
332d0c20769SMatthias Ringwald     if (initiated_call_index != -1){
333aeb0f0feSMatthias Ringwald         if (hfp_gsm_model_calls[initiated_call_index].clip_type != 0) {
334aeb0f0feSMatthias Ringwald             return hfp_gsm_model_calls[initiated_call_index].clip_number;
335d0c20769SMatthias Ringwald         }
336d0c20769SMatthias Ringwald     }
337d0c20769SMatthias Ringwald 
338d0c20769SMatthias Ringwald     int active_call_index = get_active_call_index();
339d0c20769SMatthias Ringwald     if (active_call_index != -1){
340aeb0f0feSMatthias Ringwald         if (hfp_gsm_model_calls[active_call_index].clip_type != 0) {
341aeb0f0feSMatthias Ringwald             return hfp_gsm_model_calls[active_call_index].clip_number;
342d0c20769SMatthias Ringwald         }
343d0c20769SMatthias Ringwald     }
344aeb0f0feSMatthias Ringwald     hfp_gsm_model_clip_number[0] = 0;
345aeb0f0feSMatthias Ringwald     return hfp_gsm_model_clip_number;
346d0c20769SMatthias Ringwald }
347d0c20769SMatthias Ringwald 
hfp_gsm_call_status(void)3489cae807eSMatthias Ringwald hfp_call_status_t hfp_gsm_call_status(void){
349aeb0f0feSMatthias Ringwald     if (hfp_gsm_model_get_number_active_calls() + get_number_held_calls() + get_number_response_held_calls()){
35074386ee0SMatthias Ringwald         return HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT;
35174386ee0SMatthias Ringwald     }
35274386ee0SMatthias Ringwald     return HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS;
35374386ee0SMatthias Ringwald }
35474386ee0SMatthias Ringwald 
hfp_gsm_callheld_status(void)3559cae807eSMatthias Ringwald hfp_callheld_status_t hfp_gsm_callheld_status(void){
35674386ee0SMatthias Ringwald     // @note: order is important
35774386ee0SMatthias Ringwald     if (get_number_held_calls() == 0){
35874386ee0SMatthias Ringwald         return HFP_CALLHELD_STATUS_NO_CALLS_HELD;
35974386ee0SMatthias Ringwald     }
360aeb0f0feSMatthias Ringwald     if (hfp_gsm_model_get_number_active_calls() == 0) {
36174386ee0SMatthias Ringwald         return HFP_CALLHELD_STATUS_CALL_ON_HOLD_AND_NO_ACTIVE_CALLS;
36274386ee0SMatthias Ringwald     }
36374386ee0SMatthias Ringwald     return HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED;
36474386ee0SMatthias Ringwald }
36574386ee0SMatthias Ringwald 
hfp_gsm_callsetup_status(void)3669cae807eSMatthias Ringwald hfp_callsetup_status_t hfp_gsm_callsetup_status(void){
367aeb0f0feSMatthias Ringwald     return hfp_gsm_model_callsetup_status;
36874386ee0SMatthias Ringwald }
36974386ee0SMatthias Ringwald 
hfp_gsm_response_held_active(void)3709cae807eSMatthias Ringwald static int hfp_gsm_response_held_active(void){
371d210d9c4SMatthias Ringwald     return get_response_held_call_index() != -1 ;
372d210d9c4SMatthias Ringwald }
373d210d9c4SMatthias Ringwald 
hfp_gsm_call_possible(void)374d210d9c4SMatthias Ringwald int hfp_gsm_call_possible(void){
375d210d9c4SMatthias Ringwald     return get_number_none_calls() > 0;
376d210d9c4SMatthias Ringwald }
377d210d9c4SMatthias Ringwald 
hfp_gsm_handler(hfp_ag_call_event_t event,uint8_t index,uint8_t type,const char * number)378f8737b81SMatthias Ringwald void hfp_gsm_handler(hfp_ag_call_event_t event, uint8_t index, uint8_t type, const char * number){
379d0c20769SMatthias Ringwald     int next_free_slot = get_next_free_slot();
38074386ee0SMatthias Ringwald     int current_call_index = get_active_call_index();
381d210d9c4SMatthias Ringwald     int initiated_call_index = get_initiated_call_index();
382d210d9c4SMatthias Ringwald     int held_call_index = get_held_call_index();
383d0c20769SMatthias Ringwald     int i;
384d0c20769SMatthias Ringwald 
38574386ee0SMatthias Ringwald     switch (event){
3869ff73f41SMatthias Ringwald         case HFP_AG_OUTGOING_CALL_INITIATED_BY_HF:
387fe899794SMatthias Ringwald         case HFP_AG_OUTGOING_CALL_INITIATED_BY_AG:
38874386ee0SMatthias Ringwald         case HFP_AG_OUTGOING_REDIAL_INITIATED:
38974386ee0SMatthias Ringwald             if (next_free_slot == -1){
390d210d9c4SMatthias Ringwald                 log_error("gsm: max call nr exceeded");
39174386ee0SMatthias Ringwald                 return;
39274386ee0SMatthias Ringwald             }
3939cae807eSMatthias Ringwald             create_call(HFP_ENHANCED_CALL_DIR_OUTGOING);
394d210d9c4SMatthias Ringwald             break;
39574386ee0SMatthias Ringwald 
396d210d9c4SMatthias Ringwald         case HFP_AG_OUTGOING_CALL_REJECTED:
397d210d9c4SMatthias Ringwald             if (current_call_index != -1){
398d0c20769SMatthias Ringwald                 delete_call(current_call_index);
399d210d9c4SMatthias Ringwald             }
40066a048abSMatthias Ringwald             set_callsetup_status(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS);
401d210d9c4SMatthias Ringwald             break;
402d210d9c4SMatthias Ringwald 
403d210d9c4SMatthias Ringwald         case HFP_AG_OUTGOING_CALL_ACCEPTED:
40474386ee0SMatthias Ringwald             if (current_call_index != -1){
40566a048abSMatthias Ringwald                 set_enhanced_call_status_held(current_call_index);
40674386ee0SMatthias Ringwald             }
40766a048abSMatthias Ringwald             set_callsetup_status(HFP_CALLSETUP_STATUS_OUTGOING_CALL_SETUP_IN_DIALING_STATE);
40874386ee0SMatthias Ringwald             break;
409d210d9c4SMatthias Ringwald 
41074386ee0SMatthias Ringwald         case HFP_AG_OUTGOING_CALL_RINGING:
411baa221a8SMilanka Ringwald             current_call_index = get_dialing_call_index();
412d210d9c4SMatthias Ringwald             if (current_call_index == -1){
413d210d9c4SMatthias Ringwald                 log_error("gsm: no active call");
414d210d9c4SMatthias Ringwald                 return;
415d210d9c4SMatthias Ringwald             }
41666a048abSMatthias Ringwald             set_callsetup_status(HFP_CALLSETUP_STATUS_OUTGOING_CALL_SETUP_IN_ALERTING_STATE);
41774386ee0SMatthias Ringwald             break;
41874386ee0SMatthias Ringwald         case HFP_AG_OUTGOING_CALL_ESTABLISHED:
41966a048abSMatthias Ringwald             set_callsetup_status(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS);
42066a048abSMatthias Ringwald             set_enhanced_call_status_active(initiated_call_index);
42174386ee0SMatthias Ringwald             break;
422d210d9c4SMatthias Ringwald 
423d210d9c4SMatthias Ringwald         case HFP_AG_INCOMING_CALL:
424d210d9c4SMatthias Ringwald             if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS) break;
425d7089767SMatthias Ringwald             if (next_free_slot == -1){
426d7089767SMatthias Ringwald                 log_error("gsm: max call nr exceeded");
427d7089767SMatthias Ringwald                 return;
428d7089767SMatthias Ringwald             }
42966a048abSMatthias Ringwald             set_callsetup_status(HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS);
4309cae807eSMatthias Ringwald             create_call(HFP_ENHANCED_CALL_DIR_INCOMING);
431d210d9c4SMatthias Ringwald             break;
432d210d9c4SMatthias Ringwald 
433d210d9c4SMatthias Ringwald         case HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG:
434d210d9c4SMatthias Ringwald             if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS) break;
43566a048abSMatthias Ringwald             set_callsetup_status(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS);
436d210d9c4SMatthias Ringwald 
437d210d9c4SMatthias Ringwald             if (hfp_gsm_call_status() == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){
43866a048abSMatthias Ringwald                 set_enhanced_call_status_held(current_call_index);
439d210d9c4SMatthias Ringwald             }
44066a048abSMatthias Ringwald             set_enhanced_call_status_active(initiated_call_index);
441d210d9c4SMatthias Ringwald             break;
442d210d9c4SMatthias Ringwald 
443d210d9c4SMatthias Ringwald         case HFP_AG_HELD_CALL_JOINED_BY_AG:
444d210d9c4SMatthias Ringwald             if (hfp_gsm_call_status() != HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT) break;
445d210d9c4SMatthias Ringwald 
446d210d9c4SMatthias Ringwald             // TODO: is following condition correct? Can we join incoming call before it is answered?
447aeb0f0feSMatthias Ringwald             if (hfp_gsm_model_callsetup_status == HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS){
44866a048abSMatthias Ringwald                 set_enhanced_call_status_active(initiated_call_index);
44966a048abSMatthias Ringwald                 set_callsetup_status(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS);
4509cae807eSMatthias Ringwald             } else if (hfp_gsm_callheld_status() == HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED) {
45166a048abSMatthias Ringwald                 set_enhanced_call_status_active(held_call_index);
452d210d9c4SMatthias Ringwald             }
453d210d9c4SMatthias Ringwald 
4549cae807eSMatthias Ringwald             for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
45566a048abSMatthias Ringwald                 if (is_enhanced_call_status_active(i)){
456aeb0f0feSMatthias Ringwald                     hfp_gsm_model_calls[i].mpty = HFP_ENHANCED_CALL_MPTY_CONFERENCE_CALL;
4579cae807eSMatthias Ringwald                 }
458d210d9c4SMatthias Ringwald             }
459d210d9c4SMatthias Ringwald             break;
460d210d9c4SMatthias Ringwald 
461d210d9c4SMatthias Ringwald         case HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF:
462d210d9c4SMatthias Ringwald             if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS) break;
463d210d9c4SMatthias Ringwald             if (hfp_gsm_call_status() != HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS) break;
46466a048abSMatthias Ringwald             set_callsetup_status(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS);
46566a048abSMatthias Ringwald             set_enhanced_call_status_active(initiated_call_index);
466d210d9c4SMatthias Ringwald             break;
467d210d9c4SMatthias Ringwald 
468d210d9c4SMatthias Ringwald         case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_AG:
469d210d9c4SMatthias Ringwald         case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_HF:
470d210d9c4SMatthias Ringwald             if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS) break;
471d210d9c4SMatthias Ringwald             if (hfp_gsm_call_status() != HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS) break;
47266a048abSMatthias Ringwald             set_callsetup_status(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS);
47366a048abSMatthias Ringwald             set_enhanced_call_status_response_hold(initiated_call_index);
474d210d9c4SMatthias Ringwald             break;
475d210d9c4SMatthias Ringwald 
476d210d9c4SMatthias Ringwald         case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_AG:
477d210d9c4SMatthias Ringwald         case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_HF:
478d210d9c4SMatthias Ringwald             if (!hfp_gsm_response_held_active()) break;
47966a048abSMatthias Ringwald             set_enhanced_call_status_active(get_response_held_call_index());
480d210d9c4SMatthias Ringwald             break;
481d210d9c4SMatthias Ringwald 
482d210d9c4SMatthias Ringwald         case HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_AG:
483d210d9c4SMatthias Ringwald         case HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_HF:
484d210d9c4SMatthias Ringwald             if (!hfp_gsm_response_held_active()) break;
485d0c20769SMatthias Ringwald             delete_call(get_response_held_call_index());
486d210d9c4SMatthias Ringwald             break;
487d210d9c4SMatthias Ringwald 
488d210d9c4SMatthias Ringwald 
489d210d9c4SMatthias Ringwald         case HFP_AG_TERMINATE_CALL_BY_HF:
490d210d9c4SMatthias Ringwald             switch (hfp_gsm_call_status()){
491d210d9c4SMatthias Ringwald                 case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS:
49266a048abSMatthias Ringwald                     set_callsetup_status(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS);
493d210d9c4SMatthias Ringwald                     break;
494d210d9c4SMatthias Ringwald                 case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT:
495d0c20769SMatthias Ringwald                     delete_call(current_call_index);
496d210d9c4SMatthias Ringwald                     break;
4977bbeb3adSMilanka Ringwald                 default:
4987bbeb3adSMilanka Ringwald                     break;
499d210d9c4SMatthias Ringwald             }
500d210d9c4SMatthias Ringwald             break;
501d210d9c4SMatthias Ringwald 
502d210d9c4SMatthias Ringwald         case HFP_AG_TERMINATE_CALL_BY_AG:
50366a048abSMatthias Ringwald             set_callsetup_status(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS);
504f2aa99a9SMilanka Ringwald             if (current_call_index != -1){
505d0c20769SMatthias Ringwald                 delete_call(current_call_index);
506d210d9c4SMatthias Ringwald                 break;
507f2aa99a9SMilanka Ringwald             }
508f2aa99a9SMilanka Ringwald             if (initiated_call_index != -1){
509f2aa99a9SMilanka Ringwald                 delete_call(initiated_call_index);
510*f3e773c5SMatthias Ringwald                 break;
511*f3e773c5SMatthias Ringwald             }
512*f3e773c5SMatthias Ringwald             if (held_call_index != -1) {
513*f3e773c5SMatthias Ringwald                 delete_call(held_call_index);
514*f3e773c5SMatthias Ringwald                 break;
515f2aa99a9SMilanka Ringwald             }
516f2aa99a9SMilanka Ringwald             break;
517d210d9c4SMatthias Ringwald 
518d0c20769SMatthias Ringwald         case HFP_AG_CALL_DROPPED:
51966a048abSMatthias Ringwald             set_callsetup_status(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS);
520d210d9c4SMatthias Ringwald             for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
521d0c20769SMatthias Ringwald                 delete_call(i);
522d210d9c4SMatthias Ringwald             }
523d210d9c4SMatthias Ringwald             break;
524d0c20769SMatthias Ringwald 
525d210d9c4SMatthias Ringwald         case HFP_AG_CALL_HOLD_USER_BUSY:
526d210d9c4SMatthias Ringwald             // Held or waiting call gets active,
52766a048abSMatthias Ringwald             set_callsetup_status(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS);
52866a048abSMatthias Ringwald             free_call_slot(initiated_call_index);
52966a048abSMatthias Ringwald             set_enhanced_call_status_active(held_call_index);
530d210d9c4SMatthias Ringwald             break;
531d210d9c4SMatthias Ringwald 
532d0c20769SMatthias Ringwald         case HFP_AG_CALL_HOLD_RELEASE_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL:
533c1ab6cc1SMatthias Ringwald             if ((index != 0) && (index <= HFP_GSM_MAX_NR_CALLS) ){
534d0c20769SMatthias Ringwald                 for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
535aeb0f0feSMatthias Ringwald                     if (hfp_gsm_model_calls[i].index == index){
536d0c20769SMatthias Ringwald                         delete_call(i);
537d0c20769SMatthias Ringwald                         continue;
538d0c20769SMatthias Ringwald                     }
539d0c20769SMatthias Ringwald                 }
540d0c20769SMatthias Ringwald             } else {
541d210d9c4SMatthias Ringwald                 for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
54266a048abSMatthias Ringwald                     if (is_enhanced_call_status_active(i)){
543d0c20769SMatthias Ringwald                         delete_call(i);
544d0c20769SMatthias Ringwald                     }
545d210d9c4SMatthias Ringwald                 }
546d210d9c4SMatthias Ringwald             }
547d210d9c4SMatthias Ringwald 
548aeb0f0feSMatthias Ringwald             if (hfp_gsm_model_callsetup_status != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS){
54966a048abSMatthias Ringwald                 set_enhanced_call_status_active(initiated_call_index);
550d210d9c4SMatthias Ringwald             } else {
55166a048abSMatthias Ringwald                 set_enhanced_call_status_active(held_call_index);
552d210d9c4SMatthias Ringwald             }
553d0c20769SMatthias Ringwald 
55466a048abSMatthias Ringwald             set_callsetup_status(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS);
555d210d9c4SMatthias Ringwald             break;
556d0c20769SMatthias Ringwald 
557d0c20769SMatthias Ringwald         case HFP_AG_CALL_HOLD_PARK_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL:
558d210d9c4SMatthias Ringwald             for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
559aeb0f0feSMatthias Ringwald                 if (is_enhanced_call_status_active(i) && (hfp_gsm_model_calls[i].index != index)){
56066a048abSMatthias Ringwald                     set_enhanced_call_status_held(i);
561d210d9c4SMatthias Ringwald                 }
562d210d9c4SMatthias Ringwald             }
563d210d9c4SMatthias Ringwald 
564aeb0f0feSMatthias Ringwald             if (hfp_gsm_model_callsetup_status != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS){
56566a048abSMatthias Ringwald                 set_enhanced_call_status_active(initiated_call_index);
566d210d9c4SMatthias Ringwald             } else {
56766a048abSMatthias Ringwald                 set_enhanced_call_status_active(held_call_index);
568d210d9c4SMatthias Ringwald             }
56966a048abSMatthias Ringwald             set_callsetup_status(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS);
570d210d9c4SMatthias Ringwald             break;
571d0c20769SMatthias Ringwald 
572d0c20769SMatthias Ringwald         case HFP_AG_CALL_HOLD_ADD_HELD_CALL:
573d210d9c4SMatthias Ringwald             if (hfp_gsm_callheld_status() != HFP_CALLHELD_STATUS_NO_CALLS_HELD){
574d210d9c4SMatthias Ringwald                 for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
575aeb0f0feSMatthias Ringwald                     if (hfp_gsm_model_calls[i].used_slot){
57666a048abSMatthias Ringwald                         set_enhanced_call_status_active(i);
577aeb0f0feSMatthias Ringwald                         hfp_gsm_model_calls[i].mpty = HFP_ENHANCED_CALL_MPTY_CONFERENCE_CALL;
578d210d9c4SMatthias Ringwald                     }
579d210d9c4SMatthias Ringwald                 }
580d210d9c4SMatthias Ringwald             }
581d210d9c4SMatthias Ringwald             break;
582d0c20769SMatthias Ringwald 
583d0c20769SMatthias Ringwald         case HFP_AG_CALL_HOLD_EXIT_AND_JOIN_CALLS:
584d210d9c4SMatthias Ringwald             for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
585d0c20769SMatthias Ringwald                 delete_call(i);
586d210d9c4SMatthias Ringwald             }
587d0c20769SMatthias Ringwald             break;
588d210d9c4SMatthias Ringwald 
589d0c20769SMatthias Ringwald         case HFP_AG_SET_CLIP:
590d0c20769SMatthias Ringwald             if (initiated_call_index != -1){
591d0c20769SMatthias Ringwald                 hfp_gsm_set_clip(initiated_call_index, type, number);
592d210d9c4SMatthias Ringwald                 break;
593d210d9c4SMatthias Ringwald             }
5949cae807eSMatthias Ringwald 
595aeb0f0feSMatthias Ringwald             hfp_gsm_model_clip_type = type;
596c10fde09SMatthias Ringwald             btstack_strcpy(hfp_gsm_model_clip_number, sizeof(hfp_gsm_model_clip_number), number);
597d0c20769SMatthias Ringwald             break;
59874386ee0SMatthias Ringwald         default:
59974386ee0SMatthias Ringwald             break;
60074386ee0SMatthias Ringwald     }
60174386ee0SMatthias Ringwald }
602