Example #1
0
static int hfp_ag_run_for_context_codecs_connection(hfp_connection_t * context){
    if (context->state <= HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED ||
        context->state > HFP_CODECS_CONNECTION_ESTABLISHED) return 0;

    int done = 0;
    printf(" AG run for context_codecs_connection: ");
    switch (context->state){
        case HFP_SLE_W2_EXCHANGE_COMMON_CODEC:
            if (context->ag_trigger_codec_connection_setup){ // received BCS
                printf(" send BCS \n");
                context->ag_trigger_codec_connection_setup = 0;
                context->state = HFP_SLE_W4_EXCHANGE_COMMON_CODEC;
                context->suggested_codec = hfp_ag_suggest_codec(context);
                hfp_ag_cmd_suggest_codec(context->rfcomm_cid, context->suggested_codec);
                done = 1;
                break;
            }
            break;
        case HFP_SLE_W4_EXCHANGE_COMMON_CODEC:
            switch(context->command){
                case HFP_CMD_AVAILABLE_CODECS:
                    if (context->notify_ag_on_new_codecs){ // received BAC
                        printf(" received BAC\n");
                        context->notify_ag_on_new_codecs = 0;
                        if (context->suggested_codec != hfp_ag_suggest_codec(context)){
                            context->suggested_codec = hfp_ag_suggest_codec(context);
                            context->state = HFP_SLE_W4_EXCHANGE_COMMON_CODEC;
                        }
                        hfp_ag_ok(context->rfcomm_cid);
                        done = 1;
                        break;
                    }
                    break;
                case HFP_CMD_HF_CONFIRMED_CODEC:
                    printf(" received AT+BCS\n");
                    if (context->codec_confirmed != context->suggested_codec){
                        context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
                        hfp_ag_error(context->rfcomm_cid);
                        done = 1;
                        break;
                    } 
                    context->negotiated_codec = context->codec_confirmed;
                    context->state = HFP_CODECS_CONNECTION_ESTABLISHED;
                    hfp_emit_event(hfp_callback, HFP_SUBEVENT_CODECS_CONNECTION_COMPLETE, 0);
                    hfp_ag_ok(context->rfcomm_cid);
                    done = 1;
                    break; 
                default:
                    break;
            }
            break;
            
        case HFP_CODECS_CONNECTION_ESTABLISHED:
            switch(context->command){
                case HFP_CMD_AVAILABLE_CODECS:

                    if (context->notify_ag_on_new_codecs){ // received BAC
                        context->notify_ag_on_new_codecs = 0;
                        if (context->suggested_codec != hfp_ag_suggest_codec(context)){
                            context->suggested_codec = hfp_ag_suggest_codec(context);
                            context->state = HFP_SLE_W4_EXCHANGE_COMMON_CODEC;
                        }
                        hfp_ag_ok(context->rfcomm_cid);
                        done = 1;
                        break;
                    }
                    break;
                case HFP_CMD_AG_SUGGESTED_CODEC:
                    if (context->ag_trigger_codec_connection_setup){ 
                        context->ag_trigger_codec_connection_setup = 0;
                        if (context->negotiated_codec != hfp_ag_suggest_codec(context)){
                            context->state = HFP_SLE_W4_EXCHANGE_COMMON_CODEC;
                            context->suggested_codec = hfp_ag_suggest_codec(context);
                            hfp_ag_cmd_suggest_codec(context->rfcomm_cid, context->suggested_codec);
                            done = 1;
                            break;
                        }
                    }
                    break;
                default:
                    break;
            }

        default:
            break;
    }
    return done;
}
Example #2
0
static void hfp_ag_run_for_context_service_level_connection(hfp_connection_t * context){
    if (context->state >= HFP_CODECS_CONNECTION_ESTABLISHED) return;
    printf(" AG run for context_service_level_connection \n");

    switch(context->command){
        case HFP_CMD_SUPPORTED_FEATURES:
            switch(context->state){
                case HFP_W4_EXCHANGE_SUPPORTED_FEATURES:
                    hfp_ag_exchange_supported_features_cmd(context->rfcomm_cid);
                    if (has_codec_negotiation_feature(context)){
                        context->state = HFP_W4_NOTIFY_ON_CODECS;
                        break;
                    } 
                    context->state = HFP_W4_RETRIEVE_INDICATORS;
                    break;
                default:
                    break;
            }
            break;
        case HFP_CMD_AVAILABLE_CODECS:
            switch(context->state){
                case HFP_W4_NOTIFY_ON_CODECS:
                    hfp_ag_retrieve_codec_cmd(context->rfcomm_cid);
                    context->state = HFP_W4_RETRIEVE_INDICATORS;
                    break;
                case HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED:
                    context->suggested_codec = hfp_ag_suggest_codec(context);
                    printf("received BAC == new HF codecs, suggested codec %d\n", context->suggested_codec);
                    hfp_ag_ok(context->rfcomm_cid);
                    break;

                default:
                    break;
            }
            break;
        case HFP_CMD_INDICATOR:
            switch(context->state){
                case HFP_W4_RETRIEVE_INDICATORS:
                    if (context->retrieve_ag_indicators == 0) break;
                    hfp_ag_retrieve_indicators_cmd(context->rfcomm_cid, context);
                    context->state = HFP_W4_RETRIEVE_INDICATORS_STATUS;
                    break;
                case HFP_W4_RETRIEVE_INDICATORS_STATUS:
                    if (context->retrieve_ag_indicators_status == 0) break;
                    hfp_ag_retrieve_indicators_status_cmd(context->rfcomm_cid);
                    context->state = HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE;
                    break;
                default:
                    break;
            }
            break;
        case HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE:
            switch(context->state){
                case HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE:
                    hfp_ag_toggle_indicator_status_update_cmd(context->rfcomm_cid, 1);
                    if (has_call_waiting_and_3way_calling_feature(context)){
                        context->state = HFP_W4_RETRIEVE_CAN_HOLD_CALL;
                        break;
                    }
                    if (has_hf_indicators_feature(context)){
                        context->state = HFP_W4_LIST_GENERIC_STATUS_INDICATORS;
                        break;
                    } 
                    context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
                    hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0);
                    break;
                default:
                    break;
            }
            break;
        case HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES:
            switch(context->state){
                case HFP_W4_RETRIEVE_CAN_HOLD_CALL:
                    hfp_ag_retrieve_can_hold_call_cmd(context->rfcomm_cid);
                    if (has_hf_indicators_feature(context)){
                        context->state = HFP_W4_LIST_GENERIC_STATUS_INDICATORS;
                        break;
                    } 
                    context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
                    hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0);
                    break;
                default:
                    break;
            }
            break;
        case HFP_CMD_GENERIC_STATUS_INDICATOR:
            switch(context->state){
                case HFP_W4_LIST_GENERIC_STATUS_INDICATORS:
                    if (context->list_generic_status_indicators == 0) break;
                    hfp_ag_list_supported_generic_status_indicators_cmd(context->rfcomm_cid);
                    context->state = HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS;
                    context->list_generic_status_indicators = 0;
                    break;
                case HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS:
                    if (context->retrieve_generic_status_indicators == 0) break;
                    hfp_ag_retrieve_supported_generic_status_indicators_cmd(context->rfcomm_cid);
                    context->state = HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS; 
                    context->retrieve_generic_status_indicators = 0;
                    break;
                case HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS:
                    if (context->retrieve_generic_status_indicators_state == 0) break;
                    hfp_ag_retrieve_initital_supported_generic_status_indicators_cmd(context->rfcomm_cid);
                    context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
                    context->retrieve_generic_status_indicators_state = 0;
                    hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0);
                    break;
                default:
                    break;
            }
            break;

        default:
            break;
    }
}
Example #3
0
static int hfp_ag_run_for_context_service_level_connection_queries(hfp_connection_t * context){
    if (context->state != HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) return 0;
    int done = 0;
    printf("    SLC queries: ");
    
    switch(context->command){
        case HFP_CMD_AVAILABLE_CODECS:
            context->suggested_codec = hfp_ag_suggest_codec(context);
            printf("received BAC == new HF codecs, suggested codec %d\n", context->suggested_codec);
            hfp_ag_ok(context->rfcomm_cid);
            done = 1;
            break;

        case HFP_CMD_QUERY_OPERATOR_SELECTION:
            if (context->operator_name_format == 1){
                if (context->network_operator.format != 0){
                    hfp_ag_error(context->rfcomm_cid);
                    done = 1;
                    break;
                }
                hfp_ag_ok(context->rfcomm_cid);
                done = 1;
                context->operator_name_format = 0;    
                break;
            }
            if (context->operator_name == 1){
                hfp_ag_report_network_operator_name_cmd(context->rfcomm_cid, context->network_operator);
                context->operator_name = 0;
                done = 1;
                break;
            }
            break;
        case HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE:{
                int i;
                for (i = 0; i < context->ag_indicators_nr; i++){
                    if (context->ag_indicators[i].enabled == 0) continue;
                    if (context->ag_indicators[i].status_changed == 0) continue;
                    hfp_ag_transfer_ag_indicators_status_cmd(context->rfcomm_cid, context->ag_indicators[i]);
                    done = 1;
                    context->ag_indicators[i].status_changed = 0;
                    return done;
                }
                break;
            }
        case HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP:
            if (context->hf_trigger_codec_connection_setup){ // received BCC
                printf(" received BCC \n");
                context->hf_trigger_codec_connection_setup = 0;
                context->ag_trigger_codec_connection_setup = 1;
                context->state = HFP_SLE_W2_EXCHANGE_COMMON_CODEC;
                hfp_ag_ok(context->rfcomm_cid);
                done = 1;
                return done;
            }
            
            if (context->ag_trigger_codec_connection_setup){ // received BCS
                printf(" send BCS \n");
                context->ag_trigger_codec_connection_setup = 0;
                context->state = HFP_SLE_W4_EXCHANGE_COMMON_CODEC;
                context->suggested_codec = hfp_ag_suggest_codec(context);
                hfp_ag_cmd_suggest_codec(context->rfcomm_cid, context->suggested_codec);
                done = 1;
                return done;
            }
            break;
        case HFP_CMD_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR:
            if (context->extended_audio_gateway_error){
                hfp_ag_report_extended_audio_gateway_error(context->rfcomm_cid, context->extended_audio_gateway_error);
                context->extended_audio_gateway_error = 0;
                done = 1;
                break;
            }
        case HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE:
            printf("TODO\n");
            break;
        default:
            break;
    }
    return done;
}
Example #4
0
static int codecs_exchange_state_machine(hfp_connection_t * context){
    /* events ( == commands):
        HFP_CMD_AVAILABLE_CODECS == received AT+BAC with list of codecs
        HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP:
            hf_trigger_codec_connection_setup == received BCC
            ag_trigger_codec_connection_setup == received from AG to send BCS
        HFP_CMD_HF_CONFIRMED_CODEC == received AT+BCS
    */
            
     switch (context->codecs_state){
        case HFP_CODECS_RECEIVED_TRIGGER_CODEC_EXCHANGE:
            context->command = HFP_CMD_AG_SEND_COMMON_CODEC;
            break;
        case HFP_CODECS_AG_RESEND_COMMON_CODEC:
            context->command = HFP_CMD_AG_SEND_COMMON_CODEC;
            break;
        default:
            break;
    }

    // printf(" -> State machine: CC\n");
    
    switch (context->command){
        case HFP_CMD_AVAILABLE_CODECS:
            //printf("HFP_CODECS_RECEIVED_LIST \n");
            if (context->state < HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED){
                context->codecs_state = HFP_CODECS_RECEIVED_LIST;
                hfp_ag_ok(context->rfcomm_cid);
                return 1;    
            }

            switch (context->codecs_state){
                case HFP_CODECS_AG_SENT_COMMON_CODEC:
                case HFP_CODECS_EXCHANGED:
                    context->codecs_state = HFP_CODECS_AG_RESEND_COMMON_CODEC;
                    break;
                default:
                    break;
            }
            hfp_ag_ok(context->rfcomm_cid);
            return 1;
        
        case HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP:
            //printf(" HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP \n");
            context->codecs_state = HFP_CODECS_RECEIVED_TRIGGER_CODEC_EXCHANGE;
            hfp_ag_ok(context->rfcomm_cid);
            return 1;
        
        case HFP_CMD_AG_SEND_COMMON_CODEC:
            //printf(" HFP_CMD_AG_SEND_COMMON_CODEC \n");
            context->codecs_state = HFP_CODECS_AG_SENT_COMMON_CODEC;
            context->suggested_codec = hfp_ag_suggest_codec(context);
            hfp_ag_cmd_suggest_codec(context->rfcomm_cid, context->suggested_codec);
            return 1;

        case HFP_CMD_HF_CONFIRMED_CODEC:
            //printf("HFP_CMD_HF_CONFIRMED_CODEC \n");
            if (context->codec_confirmed != context->suggested_codec){
                context->codecs_state = HFP_CODECS_ERROR;
                hfp_ag_error(context->rfcomm_cid);
                return 1;
            } 
            context->negotiated_codec = context->codec_confirmed;
            context->codecs_state = HFP_CODECS_EXCHANGED;
            hfp_emit_event(hfp_callback, HFP_SUBEVENT_CODECS_CONNECTION_COMPLETE, 0);
            hfp_ag_ok(context->rfcomm_cid);           
            return 1; 
        default:
            break;
    }
    return 0;
}