xref: /btstack/src/classic/hfp_gsm_model.c (revision 2044a9b9ae072d40605300dae349cd05c5194e66)
1 /*
2  * Copyright (C) 2014 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 // *****************************************************************************
39 //
40 // GSM Model
41 //
42 // *****************************************************************************
43 
44 #include "btstack_config.h"
45 
46 #include <stdint.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 
51 #include "btstack_memory.h"
52 #include "classic/hfp.h"
53 #include "classic/hfp_gsm_model.h"
54 #include "classic/sdp.h"
55 #include "classic/sdp_query_rfcomm.h"
56 #include "btstack_debug.h"
57 #include "hci.h"
58 #include "hci_cmd.h"
59 #include "hci_dump.h"
60 #include "l2cap.h"
61 #include "btstack_run_loop.h"
62 
63 #define HFP_GSM_MAX_NR_CALLS 3
64 #define HFP_GSM_MAX_CALL_NUMBER_SIZE 25
65 
66 static hfp_gsm_call_t gsm_calls[HFP_GSM_MAX_NR_CALLS];
67 static hfp_callsetup_status_t callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS;
68 
69 static uint8_t clip_type;
70 static char clip_number[HFP_GSM_MAX_CALL_NUMBER_SIZE];
71 static char last_dialed_number[HFP_GSM_MAX_CALL_NUMBER_SIZE];
72 
73 static void hfp_gsm_handler(hfp_ag_call_event_t event, uint8_t index, uint8_t type, const char * number);
74 
75 void hfp_gsm_init(void){
76     callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS;
77     clip_type = 0;
78     memset(clip_number, 0, sizeof(clip_number));
79     memset(last_dialed_number, 0, sizeof(last_dialed_number));
80     memset(gsm_calls, 0, sizeof(gsm_calls));
81     int i;
82     for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
83         gsm_calls[i].status = CALL_NONE;
84     }
85 }
86 
87 static int get_number_calls_with_status(hfp_gsm_call_status_t status){
88     int i, count = 0;
89     for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
90         if (gsm_calls[i].status == status) count++;
91     }
92     return count;
93 }
94 
95 static int get_call_index_with_status(hfp_gsm_call_status_t status){
96     int i ;
97     for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
98         if (gsm_calls[i].status == status) return i;
99     }
100     return -1;
101 }
102 
103 static inline int get_next_free_slot(void){
104     return get_call_index_with_status(CALL_NONE);
105 }
106 
107 static inline int get_active_call_index(void){
108     return get_call_index_with_status(CALL_ACTIVE);
109 }
110 
111 static inline int get_initiated_call_index(void){
112     return get_call_index_with_status(CALL_INITIATED);
113 }
114 
115 static inline int get_held_call_index(void){
116     return get_call_index_with_status(CALL_HELD);
117 }
118 
119 static inline int get_response_held_call_index(void){
120     return get_call_index_with_status(CALL_RESPONSE_HOLD);
121 }
122 
123 static inline int get_number_none_calls(void){
124     return get_number_calls_with_status(CALL_NONE);
125 }
126 
127 static inline int get_number_active_calls(void){
128     return get_number_calls_with_status(CALL_ACTIVE);
129 }
130 
131 static inline int get_number_held_calls(void){
132     return get_number_calls_with_status(CALL_HELD);
133 }
134 
135 static inline int get_number_response_held_calls(void){
136     return get_number_calls_with_status(CALL_RESPONSE_HOLD);
137 }
138 
139 static int next_call_index(void){
140     return HFP_GSM_MAX_NR_CALLS + 1 - get_number_none_calls();
141 }
142 
143 static void hfp_gsm_set_clip(int index_in_table, uint8_t type, const char * number){
144     if (strlen(number) == 0) return;
145 
146     gsm_calls[index_in_table].clip_type = type;
147 
148     int clip_number_size = strlen(number) < HFP_GSM_MAX_CALL_NUMBER_SIZE ? strlen(number) : HFP_GSM_MAX_CALL_NUMBER_SIZE-1;
149     strncpy(gsm_calls[index_in_table].clip_number, number, clip_number_size);
150     gsm_calls[index_in_table].clip_number[clip_number_size] = '\0';
151     strncpy(last_dialed_number, number, clip_number_size);
152     last_dialed_number[clip_number_size] = '\0';
153 
154     clip_type = 0;
155     memset(clip_number, 0, sizeof(clip_number));
156 }
157 
158 static void delete_call(int delete_index_in_table){
159     int i ;
160     for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
161         if (gsm_calls[i].index > gsm_calls[delete_index_in_table].index){
162             gsm_calls[i].index--;
163         }
164     }
165 
166     gsm_calls[delete_index_in_table].status = CALL_NONE;
167     gsm_calls[delete_index_in_table].clip_type = 0;
168     gsm_calls[delete_index_in_table].index = 0;
169     gsm_calls[delete_index_in_table].clip_number[0] = '\0';
170     gsm_calls[delete_index_in_table].mpty = HFP_ENHANCED_CALL_MPTY_NOT_A_CONFERENCE_CALL;
171 }
172 
173 
174 static void create_call(hfp_enhanced_call_dir_t direction){
175     int next_free_slot = get_next_free_slot();
176     gsm_calls[next_free_slot].direction = direction;
177     gsm_calls[next_free_slot].index = next_call_index();
178     gsm_calls[next_free_slot].status = CALL_INITIATED;
179     gsm_calls[next_free_slot].clip_type = 0;
180     gsm_calls[next_free_slot].clip_number[0] = '\0';
181     gsm_calls[next_free_slot].mpty = HFP_ENHANCED_CALL_MPTY_NOT_A_CONFERENCE_CALL;
182 
183     hfp_gsm_set_clip(next_free_slot, clip_type, clip_number);
184 }
185 
186 
187 int hfp_gsm_get_number_of_calls(void){
188     return HFP_GSM_MAX_NR_CALLS - get_number_none_calls();
189 }
190 
191 void hfp_gsm_clear_last_dialed_number(void){
192     memset(last_dialed_number, 0, sizeof(last_dialed_number));
193 }
194 
195 char * hfp_gsm_last_dialed_number(void){
196     return &last_dialed_number[0];
197 }
198 
199 hfp_gsm_call_t * hfp_gsm_call(int call_index){
200     int i;
201 
202     for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
203         hfp_gsm_call_t * call = &gsm_calls[i];
204 
205         if (call->index != call_index) continue;
206 
207         call->enhanced_status = HFP_ENHANCED_CALL_STATUS_CALL_HELD_BY_RESPONSE_AND_HOLD;
208 
209         if (call->status == CALL_ACTIVE) call->enhanced_status = HFP_ENHANCED_CALL_STATUS_ACTIVE;
210         if (call->status == CALL_HELD)   call->enhanced_status = HFP_ENHANCED_CALL_STATUS_HELD;
211 
212         if (call->status == CALL_INITIATED){
213             if (call->direction == HFP_ENHANCED_CALL_DIR_OUTGOING){
214                 if (callsetup_status == HFP_CALLSETUP_STATUS_OUTGOING_CALL_SETUP_IN_ALERTING_STATE){
215                     call->enhanced_status = HFP_ENHANCED_CALL_STATUS_OUTGOING_ALERTING;
216                 }
217                 call->enhanced_status = HFP_ENHANCED_CALL_STATUS_OUTGOING_DIALING;
218             } else {
219                 if (get_number_active_calls() > 0){
220                     call->enhanced_status = HFP_ENHANCED_CALL_STATUS_INCOMING_WAITING;
221                 }
222                 call->enhanced_status = HFP_ENHANCED_CALL_STATUS_INCOMING;
223             }
224         }
225         return call;
226     }
227     return NULL;
228 }
229 
230 uint8_t hfp_gsm_clip_type(void){
231     if (clip_type != 0) return clip_type;
232 
233     int initiated_call_index = get_initiated_call_index();
234     if (initiated_call_index != -1){
235         if (gsm_calls[initiated_call_index].clip_type != 0) {
236             return gsm_calls[initiated_call_index].clip_type;
237         }
238     }
239 
240     int active_call_index = get_active_call_index();
241     if (active_call_index != -1){
242         if (gsm_calls[active_call_index].clip_type != 0) {
243             return gsm_calls[active_call_index].clip_type;
244         }
245     }
246     return 0;
247 }
248 
249 char *  hfp_gsm_clip_number(void){
250     if (strlen(clip_number) != 0) return clip_number;
251 
252     int initiated_call_index = get_initiated_call_index();
253     if (initiated_call_index != -1){
254         if (gsm_calls[initiated_call_index].clip_type != 0) {
255             return gsm_calls[initiated_call_index].clip_number;
256         }
257     }
258 
259     int active_call_index = get_active_call_index();
260     if (active_call_index != -1){
261         if (gsm_calls[active_call_index].clip_type != 0) {
262             return gsm_calls[active_call_index].clip_number;
263         }
264     }
265     clip_number[0] = 0;
266     return clip_number;
267 }
268 
269 hfp_call_status_t hfp_gsm_call_status(void){
270     if (get_number_active_calls() + get_number_held_calls() + get_number_response_held_calls()){
271         return HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT;
272     }
273     return HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS;
274 }
275 
276 hfp_callheld_status_t hfp_gsm_callheld_status(void){
277     // @note: order is important
278     if (get_number_held_calls() == 0){
279         return HFP_CALLHELD_STATUS_NO_CALLS_HELD;
280     }
281     if (get_number_active_calls() == 0) {
282         return HFP_CALLHELD_STATUS_CALL_ON_HOLD_AND_NO_ACTIVE_CALLS;
283     }
284     return HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED;
285 }
286 
287 hfp_callsetup_status_t hfp_gsm_callsetup_status(void){
288     return callsetup_status;
289 }
290 
291 static int hfp_gsm_response_held_active(void){
292     return get_response_held_call_index() != -1 ;
293 }
294 
295 int hfp_gsm_call_possible(void){
296     return get_number_none_calls() > 0;
297 }
298 
299 void hfp_gsm_handle_event(hfp_ag_call_event_t event){
300     hfp_gsm_handler(event, 0, 0, NULL);
301 }
302 
303 void hfp_gsm_handle_event_with_clip(hfp_ag_call_event_t event, uint8_t type, const char * number){
304     hfp_gsm_handler(event, 0, type, number);
305 }
306 
307 void hfp_gsm_handle_event_with_call_index(hfp_ag_call_event_t event, uint8_t index){
308     hfp_gsm_handler(event, index, 0, NULL);
309 }
310 
311 void hfp_gsm_handle_event_with_call_number(hfp_ag_call_event_t event, const char * number){
312     hfp_gsm_handler(event, 0, 0, number);
313 }
314 
315 static void hfp_gsm_handler(hfp_ag_call_event_t event, uint8_t index, uint8_t type, const char * number){
316     int next_free_slot = get_next_free_slot();
317     int current_call_index = get_active_call_index();
318     int initiated_call_index = get_initiated_call_index();
319     int held_call_index = get_held_call_index();
320     int i;
321 
322     switch (event){
323         case HFP_AG_OUTGOING_CALL_INITIATED:
324         case HFP_AG_OUTGOING_REDIAL_INITIATED:
325             if (next_free_slot == -1){
326                 log_error("gsm: max call nr exceeded");
327                 return;
328             }
329             create_call(HFP_ENHANCED_CALL_DIR_OUTGOING);
330             break;
331 
332         case HFP_AG_OUTGOING_CALL_REJECTED:
333             if (current_call_index != -1){
334                 delete_call(current_call_index);
335             }
336             callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS;
337             break;
338 
339         case HFP_AG_OUTGOING_CALL_ACCEPTED:
340             if (current_call_index != -1){
341                 gsm_calls[current_call_index].status = CALL_HELD;
342             }
343             callsetup_status = HFP_CALLSETUP_STATUS_OUTGOING_CALL_SETUP_IN_DIALING_STATE;
344             break;
345 
346         case HFP_AG_OUTGOING_CALL_RINGING:
347             if (current_call_index == -1){
348                 log_error("gsm: no active call");
349                 return;
350             }
351             callsetup_status = HFP_CALLSETUP_STATUS_OUTGOING_CALL_SETUP_IN_ALERTING_STATE;
352             break;
353         case HFP_AG_OUTGOING_CALL_ESTABLISHED:
354             callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS;
355             gsm_calls[initiated_call_index].status = CALL_ACTIVE;
356             break;
357 
358         case HFP_AG_INCOMING_CALL:
359             if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS) break;
360             callsetup_status = HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS;
361             create_call(HFP_ENHANCED_CALL_DIR_INCOMING);
362             break;
363 
364         case HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG:
365             if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS) break;
366             callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS;
367 
368             if (hfp_gsm_call_status() == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){
369                 gsm_calls[current_call_index].status = CALL_HELD;
370             }
371             gsm_calls[initiated_call_index].status = CALL_ACTIVE;
372             break;
373 
374         case HFP_AG_HELD_CALL_JOINED_BY_AG:
375             if (hfp_gsm_call_status() != HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT) break;
376 
377             // TODO: is following condition correct? Can we join incoming call before it is answered?
378             if (callsetup_status == HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS){
379                 gsm_calls[initiated_call_index].status = CALL_ACTIVE;
380                 callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS;
381             } else if (hfp_gsm_callheld_status() == HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED) {
382                 gsm_calls[held_call_index].status = CALL_ACTIVE;
383             }
384 
385             for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
386                 if (gsm_calls[i].status == CALL_ACTIVE){
387                     gsm_calls[i].mpty = HFP_ENHANCED_CALL_MPTY_CONFERENCE_CALL;
388                 }
389             }
390             break;
391 
392         case HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF:
393             if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS) break;
394             if (hfp_gsm_call_status() != HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS) break;
395             callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS;
396             gsm_calls[initiated_call_index].status = CALL_ACTIVE;
397             break;
398 
399         case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_AG:
400         case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_HF:
401             if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS) break;
402             if (hfp_gsm_call_status() != HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS) break;
403             callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS;
404             gsm_calls[initiated_call_index].status = CALL_RESPONSE_HOLD;
405             break;
406 
407         case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_AG:
408         case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_HF:
409             if (!hfp_gsm_response_held_active()) break;
410             gsm_calls[get_response_held_call_index()].status = CALL_ACTIVE;
411             break;
412 
413         case HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_AG:
414         case HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_HF:
415             if (!hfp_gsm_response_held_active()) break;
416             delete_call(get_response_held_call_index());
417             break;
418 
419 
420         case HFP_AG_TERMINATE_CALL_BY_HF:
421             switch (hfp_gsm_call_status()){
422                 case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS:
423                     callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS;
424                     break;
425                 case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT:
426                     delete_call(current_call_index);
427                     break;
428             }
429             break;
430 
431         case HFP_AG_TERMINATE_CALL_BY_AG:
432             switch (hfp_gsm_call_status()){
433                 case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS:
434                     if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS) break;
435                     callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS;
436                     break;
437                 case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT:
438                     callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS;
439                     delete_call(current_call_index);
440                     break;
441                 default:
442                     break;
443             }
444             break;
445 
446         case HFP_AG_CALL_DROPPED:
447             callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS;
448             if (hfp_gsm_call_status() != HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT) break;
449 
450             for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
451                 delete_call(i);
452             }
453             break;
454 
455         case HFP_AG_CALL_HOLD_USER_BUSY:
456             // Held or waiting call gets active,
457             callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS;
458             gsm_calls[initiated_call_index].status = CALL_NONE;
459             gsm_calls[held_call_index].status = CALL_ACTIVE;
460             break;
461 
462         case HFP_AG_CALL_HOLD_RELEASE_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL:
463             if (index != 0 && index <= HFP_GSM_MAX_NR_CALLS ){
464                 for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
465                     if (gsm_calls[i].index == index){
466                         delete_call(i);
467                         continue;
468                     }
469                 }
470             } else {
471                 for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
472                     if (gsm_calls[i].status == CALL_ACTIVE){
473                         delete_call(i);
474                     }
475                 }
476             }
477 
478             if (callsetup_status != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS){
479                 gsm_calls[initiated_call_index].status = CALL_ACTIVE;
480             } else {
481                 gsm_calls[held_call_index].status = CALL_ACTIVE;
482             }
483 
484             callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS;
485             break;
486 
487         case HFP_AG_CALL_HOLD_PARK_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL:
488             for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
489                 if (gsm_calls[i].status == CALL_ACTIVE && gsm_calls[i].index != index){
490                     gsm_calls[i].status = CALL_HELD;
491                 }
492             }
493 
494             if (callsetup_status != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS){
495                 gsm_calls[initiated_call_index].status = CALL_ACTIVE;
496             } else {
497                 gsm_calls[held_call_index].status = CALL_ACTIVE;
498             }
499             callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS;
500             break;
501 
502         case HFP_AG_CALL_HOLD_ADD_HELD_CALL:
503             if (hfp_gsm_callheld_status() != HFP_CALLHELD_STATUS_NO_CALLS_HELD){
504                 for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
505                     if (gsm_calls[i].status != CALL_NONE){
506                         gsm_calls[i].status = CALL_ACTIVE;
507                         gsm_calls[i].mpty = HFP_ENHANCED_CALL_MPTY_CONFERENCE_CALL;
508                     }
509                 }
510             }
511             break;
512 
513         case HFP_AG_CALL_HOLD_EXIT_AND_JOIN_CALLS:
514             for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){
515                 delete_call(i);
516             }
517             break;
518 
519         case HFP_AG_SET_CLIP:
520             if (initiated_call_index != -1){
521                 hfp_gsm_set_clip(initiated_call_index, type, number);
522                 break;
523             }
524 
525             clip_type = type;
526             strncpy(clip_number, number, sizeof(clip_number));
527             clip_number[sizeof(clip_number)-1] = '\0';
528 
529             break;
530         default:
531             break;
532     }
533 }