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 2374386ee0SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 2474386ee0SMatthias Ringwald * RINGWALD 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 */ 3774386ee0SMatthias Ringwald 3874386ee0SMatthias Ringwald // ***************************************************************************** 3974386ee0SMatthias Ringwald // 4074386ee0SMatthias Ringwald // Minimal setup for HFP Audio Gateway (AG) unit (!! UNDER DEVELOPMENT !!) 4174386ee0SMatthias Ringwald // 4274386ee0SMatthias Ringwald // ***************************************************************************** 4374386ee0SMatthias Ringwald 4474386ee0SMatthias Ringwald #include "btstack-config.h" 4574386ee0SMatthias Ringwald 4674386ee0SMatthias Ringwald #include <stdint.h> 4774386ee0SMatthias Ringwald #include <stdio.h> 4874386ee0SMatthias Ringwald #include <stdlib.h> 4974386ee0SMatthias Ringwald #include <string.h> 5074386ee0SMatthias Ringwald 5174386ee0SMatthias Ringwald #include "btstack_memory.h" 5274386ee0SMatthias Ringwald #include "classic/hfp.h" 5374386ee0SMatthias Ringwald #include "classic/hfp_gsm_model.h" 5474386ee0SMatthias Ringwald #include "classic/sdp.h" 5574386ee0SMatthias Ringwald #include "classic/sdp_query_rfcomm.h" 5674386ee0SMatthias Ringwald #include "debug.h" 5774386ee0SMatthias Ringwald #include "hci.h" 5874386ee0SMatthias Ringwald #include "hci_cmds.h" 5974386ee0SMatthias Ringwald #include "hci_dump.h" 6074386ee0SMatthias Ringwald #include "l2cap.h" 6174386ee0SMatthias Ringwald #include "run_loop.h" 6274386ee0SMatthias Ringwald 6374386ee0SMatthias Ringwald #define HFP_GSM_MAX_NR_CALLS 3 6474386ee0SMatthias Ringwald 6574386ee0SMatthias Ringwald typedef enum{ 6674386ee0SMatthias Ringwald CALL_NONE, 67*d210d9c4SMatthias Ringwald CALL_INITIATED, 68*d210d9c4SMatthias Ringwald CALL_RESPONSE_HOLD, 6974386ee0SMatthias Ringwald CALL_ACTIVE, 7074386ee0SMatthias Ringwald CALL_HELD 7174386ee0SMatthias Ringwald } hfp_gsm_call_status_t; 7274386ee0SMatthias Ringwald 7374386ee0SMatthias Ringwald 7474386ee0SMatthias Ringwald typedef struct { 7574386ee0SMatthias Ringwald hfp_gsm_call_status_t status; 76*d210d9c4SMatthias Ringwald uint8_t clip_type; 77*d210d9c4SMatthias Ringwald char clip_number[25]; 7874386ee0SMatthias Ringwald } hfp_gsm_call_t; 7974386ee0SMatthias Ringwald 8074386ee0SMatthias Ringwald static hfp_gsm_call_t gsm_calls[HFP_GSM_MAX_NR_CALLS]; 8174386ee0SMatthias Ringwald static hfp_callsetup_status_t callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; 8274386ee0SMatthias Ringwald 83*d210d9c4SMatthias Ringwald void hfp_gsm_init(void){ 84*d210d9c4SMatthias Ringwald memset(gsm_calls, 0, sizeof(gsm_calls)); 85*d210d9c4SMatthias Ringwald int i; 86*d210d9c4SMatthias Ringwald for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){ 87*d210d9c4SMatthias Ringwald gsm_calls[i].status = CALL_NONE; 88*d210d9c4SMatthias Ringwald } 89*d210d9c4SMatthias Ringwald callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; 90*d210d9c4SMatthias Ringwald } 9174386ee0SMatthias Ringwald 9274386ee0SMatthias Ringwald static int get_number_calls_with_status(hfp_gsm_call_status_t status){ 9374386ee0SMatthias Ringwald int i, count = 0; 9474386ee0SMatthias Ringwald for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){ 9574386ee0SMatthias Ringwald if (gsm_calls[i].status == status) count++; 9674386ee0SMatthias Ringwald } 9774386ee0SMatthias Ringwald return count; 9874386ee0SMatthias Ringwald } 9974386ee0SMatthias Ringwald 10074386ee0SMatthias Ringwald static int get_call_index_with_status(hfp_gsm_call_status_t status){ 10174386ee0SMatthias Ringwald int i ; 10274386ee0SMatthias Ringwald for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){ 10374386ee0SMatthias Ringwald if (gsm_calls[i].status == status) return i; 10474386ee0SMatthias Ringwald } 10574386ee0SMatthias Ringwald return -1; 10674386ee0SMatthias Ringwald } 10774386ee0SMatthias Ringwald 10874386ee0SMatthias Ringwald static inline int get_none_call_index(){ 10974386ee0SMatthias Ringwald return get_call_index_with_status(CALL_NONE); 11074386ee0SMatthias Ringwald } 11174386ee0SMatthias Ringwald 11274386ee0SMatthias Ringwald static inline int get_active_call_index(){ 11374386ee0SMatthias Ringwald return get_call_index_with_status(CALL_ACTIVE); 11474386ee0SMatthias Ringwald } 11574386ee0SMatthias Ringwald 116*d210d9c4SMatthias Ringwald static inline int get_initiated_call_index(){ 117*d210d9c4SMatthias Ringwald return get_call_index_with_status(CALL_INITIATED); 118*d210d9c4SMatthias Ringwald } 119*d210d9c4SMatthias Ringwald 120*d210d9c4SMatthias Ringwald static inline int get_held_call_index(){ 121*d210d9c4SMatthias Ringwald return get_call_index_with_status(CALL_HELD); 122*d210d9c4SMatthias Ringwald } 123*d210d9c4SMatthias Ringwald 124*d210d9c4SMatthias Ringwald static inline int get_response_held_call_index(){ 125*d210d9c4SMatthias Ringwald return get_call_index_with_status(CALL_RESPONSE_HOLD); 126*d210d9c4SMatthias Ringwald } 127*d210d9c4SMatthias Ringwald 128*d210d9c4SMatthias Ringwald static inline int get_number_none_calls(){ 129*d210d9c4SMatthias Ringwald return get_number_calls_with_status(CALL_NONE); 130*d210d9c4SMatthias Ringwald } 13174386ee0SMatthias Ringwald 13274386ee0SMatthias Ringwald static inline int get_number_active_calls(){ 13374386ee0SMatthias Ringwald return get_number_calls_with_status(CALL_ACTIVE); 13474386ee0SMatthias Ringwald } 13574386ee0SMatthias Ringwald 13674386ee0SMatthias Ringwald static inline int get_number_held_calls(){ 13774386ee0SMatthias Ringwald return get_number_calls_with_status(CALL_HELD); 13874386ee0SMatthias Ringwald } 13974386ee0SMatthias Ringwald 140*d210d9c4SMatthias Ringwald static inline int get_number_response_held_calls(){ 141*d210d9c4SMatthias Ringwald return get_number_calls_with_status(CALL_RESPONSE_HOLD); 142*d210d9c4SMatthias Ringwald } 143*d210d9c4SMatthias Ringwald 14474386ee0SMatthias Ringwald hfp_call_status_t hfp_gsm_call_status(){ 145*d210d9c4SMatthias Ringwald if (get_number_active_calls() + get_number_held_calls() + get_number_response_held_calls()){ 14674386ee0SMatthias Ringwald return HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT; 14774386ee0SMatthias Ringwald } 14874386ee0SMatthias Ringwald return HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS; 14974386ee0SMatthias Ringwald } 15074386ee0SMatthias Ringwald 15174386ee0SMatthias Ringwald hfp_callheld_status_t hfp_gsm_callheld_status(){ 15274386ee0SMatthias Ringwald // @note: order is important 15374386ee0SMatthias Ringwald if (get_number_held_calls() == 0){ 15474386ee0SMatthias Ringwald return HFP_CALLHELD_STATUS_NO_CALLS_HELD; 15574386ee0SMatthias Ringwald } 15674386ee0SMatthias Ringwald if (get_number_active_calls() == 0) { 15774386ee0SMatthias Ringwald return HFP_CALLHELD_STATUS_CALL_ON_HOLD_AND_NO_ACTIVE_CALLS; 15874386ee0SMatthias Ringwald } 15974386ee0SMatthias Ringwald return HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED; 16074386ee0SMatthias Ringwald } 16174386ee0SMatthias Ringwald 16274386ee0SMatthias Ringwald hfp_callsetup_status_t hfp_gsm_callsetup_status(){ 16374386ee0SMatthias Ringwald return callsetup_status; 16474386ee0SMatthias Ringwald } 16574386ee0SMatthias Ringwald 166*d210d9c4SMatthias Ringwald int hfp_gsm_response_held_active(){ 167*d210d9c4SMatthias Ringwald return get_response_held_call_index() != -1 ; 168*d210d9c4SMatthias Ringwald } 169*d210d9c4SMatthias Ringwald 170*d210d9c4SMatthias Ringwald int hfp_gsm_call_possible(void){ 171*d210d9c4SMatthias Ringwald return get_number_none_calls() > 0; 172*d210d9c4SMatthias Ringwald } 173*d210d9c4SMatthias Ringwald 17474386ee0SMatthias Ringwald void hfp_gsm_handle_event(hfp_ag_call_event_t event){ 17574386ee0SMatthias Ringwald int next_free_slot = get_none_call_index(); 17674386ee0SMatthias Ringwald int current_call_index = get_active_call_index(); 177*d210d9c4SMatthias Ringwald int initiated_call_index = get_initiated_call_index(); 178*d210d9c4SMatthias Ringwald int held_call_index = get_held_call_index(); 179*d210d9c4SMatthias Ringwald printf("hfp_gsm_handle_event %d \n", event); 18074386ee0SMatthias Ringwald switch (event){ 18174386ee0SMatthias Ringwald case HFP_AG_OUTGOING_CALL_INITIATED: 18274386ee0SMatthias Ringwald case HFP_AG_OUTGOING_REDIAL_INITIATED: 18374386ee0SMatthias Ringwald if (next_free_slot == -1){ 184*d210d9c4SMatthias Ringwald log_error("gsm: max call nr exceeded"); 18574386ee0SMatthias Ringwald return; 18674386ee0SMatthias Ringwald } 187*d210d9c4SMatthias Ringwald break; 18874386ee0SMatthias Ringwald 189*d210d9c4SMatthias Ringwald case HFP_AG_OUTGOING_CALL_REJECTED: 190*d210d9c4SMatthias Ringwald if (current_call_index != -1){ 191*d210d9c4SMatthias Ringwald gsm_calls[current_call_index].status = CALL_NONE; 192*d210d9c4SMatthias Ringwald } 193*d210d9c4SMatthias Ringwald callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; 194*d210d9c4SMatthias Ringwald break; 195*d210d9c4SMatthias Ringwald 196*d210d9c4SMatthias Ringwald case HFP_AG_OUTGOING_CALL_ACCEPTED: 19774386ee0SMatthias Ringwald if (current_call_index != -1){ 19874386ee0SMatthias Ringwald gsm_calls[current_call_index].status = CALL_HELD; 19974386ee0SMatthias Ringwald } 200*d210d9c4SMatthias Ringwald gsm_calls[next_free_slot].status = CALL_INITIATED; 20174386ee0SMatthias Ringwald callsetup_status = HFP_CALLSETUP_STATUS_OUTGOING_CALL_SETUP_IN_DIALING_STATE; 20274386ee0SMatthias Ringwald break; 203*d210d9c4SMatthias Ringwald 20474386ee0SMatthias Ringwald case HFP_AG_OUTGOING_CALL_RINGING: 205*d210d9c4SMatthias Ringwald if (current_call_index == -1){ 206*d210d9c4SMatthias Ringwald log_error("gsm: no active call"); 207*d210d9c4SMatthias Ringwald return; 208*d210d9c4SMatthias Ringwald } 209*d210d9c4SMatthias Ringwald callsetup_status = HFP_CALLSETUP_STATUS_OUTGOING_CALL_SETUP_IN_ALERTING_STATE; 21074386ee0SMatthias Ringwald break; 21174386ee0SMatthias Ringwald case HFP_AG_OUTGOING_CALL_ESTABLISHED: 212*d210d9c4SMatthias Ringwald callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; 213*d210d9c4SMatthias Ringwald gsm_calls[initiated_call_index].status = CALL_ACTIVE; 21474386ee0SMatthias Ringwald break; 215*d210d9c4SMatthias Ringwald 216*d210d9c4SMatthias Ringwald case HFP_AG_INCOMING_CALL: 217*d210d9c4SMatthias Ringwald if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS) break; 218*d210d9c4SMatthias Ringwald callsetup_status = HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS; 219*d210d9c4SMatthias Ringwald gsm_calls[next_free_slot].status = CALL_INITIATED; 220*d210d9c4SMatthias Ringwald gsm_calls[next_free_slot].clip_type = 0; 221*d210d9c4SMatthias Ringwald break; 222*d210d9c4SMatthias Ringwald 223*d210d9c4SMatthias Ringwald case HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG: 224*d210d9c4SMatthias Ringwald if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS) break; 225*d210d9c4SMatthias Ringwald callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; 226*d210d9c4SMatthias Ringwald 227*d210d9c4SMatthias Ringwald if (hfp_gsm_call_status() == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){ 228*d210d9c4SMatthias Ringwald gsm_calls[current_call_index].status = CALL_HELD; 229*d210d9c4SMatthias Ringwald } 230*d210d9c4SMatthias Ringwald gsm_calls[initiated_call_index].status = CALL_ACTIVE; 231*d210d9c4SMatthias Ringwald break; 232*d210d9c4SMatthias Ringwald 233*d210d9c4SMatthias Ringwald case HFP_AG_HELD_CALL_JOINED_BY_AG: 234*d210d9c4SMatthias Ringwald if (hfp_gsm_call_status() != HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT) break; 235*d210d9c4SMatthias Ringwald 236*d210d9c4SMatthias Ringwald // TODO: mark joined calls with "multiparty flag" (if we cannot calculate it otherwise) 237*d210d9c4SMatthias Ringwald // TODO: is following condition correct? Can we join incoming call before it is answered? 238*d210d9c4SMatthias Ringwald if (callsetup_status == HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS){ 239*d210d9c4SMatthias Ringwald gsm_calls[initiated_call_index].status = CALL_ACTIVE; 240*d210d9c4SMatthias Ringwald callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; 241*d210d9c4SMatthias Ringwald break; 242*d210d9c4SMatthias Ringwald } 243*d210d9c4SMatthias Ringwald 244*d210d9c4SMatthias Ringwald if (hfp_gsm_callheld_status() == HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED) { 245*d210d9c4SMatthias Ringwald gsm_calls[held_call_index].status = CALL_ACTIVE; 246*d210d9c4SMatthias Ringwald break; 247*d210d9c4SMatthias Ringwald } 248*d210d9c4SMatthias Ringwald break; 249*d210d9c4SMatthias Ringwald 250*d210d9c4SMatthias Ringwald case HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF: 251*d210d9c4SMatthias Ringwald if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS) break; 252*d210d9c4SMatthias Ringwald if (hfp_gsm_call_status() != HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS) break; 253*d210d9c4SMatthias Ringwald callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; 254*d210d9c4SMatthias Ringwald gsm_calls[initiated_call_index].status = CALL_ACTIVE; 255*d210d9c4SMatthias Ringwald break; 256*d210d9c4SMatthias Ringwald 257*d210d9c4SMatthias Ringwald case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_AG: 258*d210d9c4SMatthias Ringwald case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_HF: 259*d210d9c4SMatthias Ringwald if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS) break; 260*d210d9c4SMatthias Ringwald if (hfp_gsm_call_status() != HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS) break; 261*d210d9c4SMatthias Ringwald callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; 262*d210d9c4SMatthias Ringwald gsm_calls[initiated_call_index].status = CALL_RESPONSE_HOLD; 263*d210d9c4SMatthias Ringwald break; 264*d210d9c4SMatthias Ringwald 265*d210d9c4SMatthias Ringwald case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_AG: 266*d210d9c4SMatthias Ringwald case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_HF: 267*d210d9c4SMatthias Ringwald if (!hfp_gsm_response_held_active()) break; 268*d210d9c4SMatthias Ringwald gsm_calls[get_response_held_call_index()].status = CALL_ACTIVE; 269*d210d9c4SMatthias Ringwald break; 270*d210d9c4SMatthias Ringwald 271*d210d9c4SMatthias Ringwald case HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_AG: 272*d210d9c4SMatthias Ringwald case HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_HF: 273*d210d9c4SMatthias Ringwald if (!hfp_gsm_response_held_active()) break; 274*d210d9c4SMatthias Ringwald gsm_calls[get_response_held_call_index()].status = CALL_NONE; 275*d210d9c4SMatthias Ringwald break; 276*d210d9c4SMatthias Ringwald 277*d210d9c4SMatthias Ringwald 278*d210d9c4SMatthias Ringwald case HFP_AG_TERMINATE_CALL_BY_HF: 279*d210d9c4SMatthias Ringwald switch (hfp_gsm_call_status()){ 280*d210d9c4SMatthias Ringwald case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: 281*d210d9c4SMatthias Ringwald callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; 282*d210d9c4SMatthias Ringwald break; 283*d210d9c4SMatthias Ringwald case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT: 284*d210d9c4SMatthias Ringwald gsm_calls[current_call_index].status = CALL_NONE; 285*d210d9c4SMatthias Ringwald break; 286*d210d9c4SMatthias Ringwald } 287*d210d9c4SMatthias Ringwald break; 288*d210d9c4SMatthias Ringwald 289*d210d9c4SMatthias Ringwald case HFP_AG_TERMINATE_CALL_BY_AG: 290*d210d9c4SMatthias Ringwald switch (hfp_gsm_call_status()){ 291*d210d9c4SMatthias Ringwald case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: 292*d210d9c4SMatthias Ringwald if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS) break; 293*d210d9c4SMatthias Ringwald callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; 294*d210d9c4SMatthias Ringwald break; 295*d210d9c4SMatthias Ringwald case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT: 296*d210d9c4SMatthias Ringwald callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; 297*d210d9c4SMatthias Ringwald gsm_calls[current_call_index].status = CALL_NONE; 298*d210d9c4SMatthias Ringwald break; 299*d210d9c4SMatthias Ringwald default: 300*d210d9c4SMatthias Ringwald break; 301*d210d9c4SMatthias Ringwald } 302*d210d9c4SMatthias Ringwald break; 303*d210d9c4SMatthias Ringwald 304*d210d9c4SMatthias Ringwald case HFP_AG_CALL_DROPPED:{ 305*d210d9c4SMatthias Ringwald callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; 306*d210d9c4SMatthias Ringwald if (hfp_gsm_call_status() != HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT) break; 307*d210d9c4SMatthias Ringwald 308*d210d9c4SMatthias Ringwald int i ; 309*d210d9c4SMatthias Ringwald for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){ 310*d210d9c4SMatthias Ringwald gsm_calls[i].status = CALL_NONE; 311*d210d9c4SMatthias Ringwald gsm_calls[i].clip_type = 0; 312*d210d9c4SMatthias Ringwald gsm_calls[i].clip_number[0] = '\0'; 313*d210d9c4SMatthias Ringwald } 314*d210d9c4SMatthias Ringwald } 315*d210d9c4SMatthias Ringwald break; 316*d210d9c4SMatthias Ringwald case HFP_AG_CALL_HOLD_USER_BUSY: 317*d210d9c4SMatthias Ringwald // Held or waiting call gets active, 318*d210d9c4SMatthias Ringwald callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; 319*d210d9c4SMatthias Ringwald gsm_calls[initiated_call_index].status = CALL_NONE; 320*d210d9c4SMatthias Ringwald gsm_calls[held_call_index].status = CALL_ACTIVE; 321*d210d9c4SMatthias Ringwald break; 322*d210d9c4SMatthias Ringwald 323*d210d9c4SMatthias Ringwald case HFP_AG_CALL_HOLD_RELEASE_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL:{ 324*d210d9c4SMatthias Ringwald int i ; 325*d210d9c4SMatthias Ringwald for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){ 326*d210d9c4SMatthias Ringwald if (gsm_calls[i].status == CALL_ACTIVE){ 327*d210d9c4SMatthias Ringwald gsm_calls[i].clip_type = 0; 328*d210d9c4SMatthias Ringwald gsm_calls[i].clip_number[0] = '\0'; 329*d210d9c4SMatthias Ringwald gsm_calls[i].status = CALL_NONE; 330*d210d9c4SMatthias Ringwald } 331*d210d9c4SMatthias Ringwald } 332*d210d9c4SMatthias Ringwald 333*d210d9c4SMatthias Ringwald if (callsetup_status != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS){ 334*d210d9c4SMatthias Ringwald gsm_calls[initiated_call_index].status = CALL_ACTIVE; 335*d210d9c4SMatthias Ringwald } else { 336*d210d9c4SMatthias Ringwald gsm_calls[held_call_index].status = CALL_ACTIVE; 337*d210d9c4SMatthias Ringwald } 338*d210d9c4SMatthias Ringwald callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; 339*d210d9c4SMatthias Ringwald break; 340*d210d9c4SMatthias Ringwald } 341*d210d9c4SMatthias Ringwald case HFP_AG_CALL_HOLD_PARK_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL:{ 342*d210d9c4SMatthias Ringwald int i ; 343*d210d9c4SMatthias Ringwald for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){ 344*d210d9c4SMatthias Ringwald if (gsm_calls[i].status == CALL_ACTIVE){ 345*d210d9c4SMatthias Ringwald gsm_calls[i].clip_type = 0; 346*d210d9c4SMatthias Ringwald gsm_calls[i].clip_number[0] = '\0'; 347*d210d9c4SMatthias Ringwald gsm_calls[i].status = CALL_HELD; 348*d210d9c4SMatthias Ringwald } 349*d210d9c4SMatthias Ringwald } 350*d210d9c4SMatthias Ringwald 351*d210d9c4SMatthias Ringwald if (callsetup_status != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS){ 352*d210d9c4SMatthias Ringwald gsm_calls[initiated_call_index].status = CALL_ACTIVE; 353*d210d9c4SMatthias Ringwald } else { 354*d210d9c4SMatthias Ringwald gsm_calls[held_call_index].status = CALL_ACTIVE; 355*d210d9c4SMatthias Ringwald } 356*d210d9c4SMatthias Ringwald callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; 357*d210d9c4SMatthias Ringwald break; 358*d210d9c4SMatthias Ringwald } 359*d210d9c4SMatthias Ringwald case HFP_AG_CALL_HOLD_ADD_HELD_CALL:{ 360*d210d9c4SMatthias Ringwald if (hfp_gsm_callheld_status() != HFP_CALLHELD_STATUS_NO_CALLS_HELD){ 361*d210d9c4SMatthias Ringwald int i ; 362*d210d9c4SMatthias Ringwald for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){ 363*d210d9c4SMatthias Ringwald if (gsm_calls[i].status == CALL_HELD){ 364*d210d9c4SMatthias Ringwald gsm_calls[i].clip_type = 0; 365*d210d9c4SMatthias Ringwald gsm_calls[i].clip_number[0] = '\0'; 366*d210d9c4SMatthias Ringwald gsm_calls[i].status = CALL_ACTIVE; 367*d210d9c4SMatthias Ringwald } 368*d210d9c4SMatthias Ringwald } 369*d210d9c4SMatthias Ringwald } 370*d210d9c4SMatthias Ringwald gsm_calls[initiated_call_index].status = CALL_ACTIVE; 371*d210d9c4SMatthias Ringwald 372*d210d9c4SMatthias Ringwald break; 373*d210d9c4SMatthias Ringwald } 374*d210d9c4SMatthias Ringwald case HFP_AG_CALL_HOLD_EXIT_AND_JOIN_CALLS:{ 375*d210d9c4SMatthias Ringwald int i ; 376*d210d9c4SMatthias Ringwald for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){ 377*d210d9c4SMatthias Ringwald gsm_calls[i].clip_type = 0; 378*d210d9c4SMatthias Ringwald gsm_calls[i].clip_number[0] = '\0'; 379*d210d9c4SMatthias Ringwald gsm_calls[i].status = CALL_NONE; 380*d210d9c4SMatthias Ringwald } 381*d210d9c4SMatthias Ringwald 382*d210d9c4SMatthias Ringwald break; 383*d210d9c4SMatthias Ringwald } 38474386ee0SMatthias Ringwald default: 38574386ee0SMatthias Ringwald break; 38674386ee0SMatthias Ringwald } 38774386ee0SMatthias Ringwald }