/**************************************************************************** Profile handler function called in response to issuing an AGHFP_INTERNAL_CALL_MGR_CREATE_WITH_AUDIO_REQ message. Will actually begin the call creation process. */ void aghfpHandleCallCreateAudio (AGHFP *aghfp, AGHFP_INTERNAL_CALL_MGR_CREATE_WITH_AUDIO_REQ_T *req) { /* B-11839: should validate parameters here? */ if ( aghfp->audio_connection_state!=aghfp_audio_connected ) { if ( aghfp->audio_connection_state==aghfp_audio_disconnected || aghfp->audio_connection_state==aghfp_audio_codec_connect ) /* Carry on if we've just completed codec negotiation. */ { if ( aghfpStoreAudioParams(aghfp, req->packet_type, &req->audio_params) ) { aghfp->call_params.call_type = req->call_type; aghfp->call_params.in_band = req->in_band; aghfpManageCall(aghfp, CallEventCreate, CallFlagOpenAudio); } else { aghfpSendCallCreateCfmToApp(aghfp, aghfp_call_create_invalid_params); } } else { aghfpSendCallCreateCfmToApp(aghfp, aghfp_call_create_audio_handler_active); } } else { aghfpSendCallCreateCfmToApp(aghfp, aghfp_call_create_have_audio); } }
static void manageCallWaitAudioCancel (AGHFP *aghfp, aghfp_call_event call_event, aghfp_call_flags call_flags) { switch ( call_event ) { case CallEventCreate: case CallEventAnswer: case CallEventRemoteAnswered: case CallEventTerminate: case CallEventAudioConnected: break; case CallEventAudioDisconnected: setCallFlags(aghfp, call_flags & (CallFlagsAll)); if ( checkCallFlag(aghfp, CallFlagSuccess) ) { /* Audio disconnect succeeded */ clearCallFlags(aghfp, CallFlagSuccess); if ( !usingHsp(aghfp) ) { aghfpSendCallIndicator(aghfp, aghfp_call_none); aghfpSendCallSetupIndicator(aghfp, aghfp_call_setup_none); } setCallProgress(aghfp, CallProgressIdle); aghfpSetState(aghfp, aghfp_slc_connected); aghfpSendCallCreateCfmToApp(aghfp, aghfp_call_create_aborted); } else { /* Audio disconnect failed */ Panic(); /* B-11841: Should do something more meaningful here */ } break; case CallEventAudioTransfer: case CallEventRing: case CallEventTerminateHeld: case CallEventAcceptHeld: break; case CallEventSlcRemoved: /* SLC has been removed */ setCallProgress(aghfp, CallProgressIdle); aghfpSetState(aghfp, aghfp_ready); aghfpSendCallCreateCfmToApp(aghfp, aghfp_call_create_slc_removed); aghfpSendSlcDisconnectIndToApp(aghfp, convertCallFlagToDisconnectStatus(call_flags)); break; default: Panic(); } }
/**************************************************************************** Profile handler function called in response to issuing an AGHFP_INTERNAL_CALL_MGR_CREATE_REQ message. Will actually begin the call creation process. */ void aghfpHandleCallCreate (AGHFP *aghfp, AGHFP_INTERNAL_CALL_MGR_CREATE_REQ_T *req) { /* B-11839: should validate parameters here? */ if ( aghfp->audio_connection_state==aghfp_audio_disconnected || aghfp->audio_connection_state==aghfp_audio_connected ) { aghfp->call_params.call_type = req->call_type; aghfp->call_params.in_band = req->in_band; aghfpManageCall(aghfp, CallEventCreate, CallFlagsNone); } else { aghfpSendCallCreateCfmToApp(aghfp, aghfp_call_create_audio_handler_active); } }
static void handleAghfpMessages(Task task, MessageId id, Message message) { AGHFP *aghfp = (AGHFP *) task; aghfp_state profileState = aghfp->state; switch(id) { /*************************************************************************/ /* Init messages */ /*************************************************************************/ case AGHFP_INTERNAL_INIT_REQ: PRINT(("AGHFP_INTERNAL_INIT_REQ\n")); switch(profileState) { case aghfp_initialising: aghfpHandleInternalInitReq(aghfp); break; default: handleUnexpected(aghfpUnexpectedAghfpPrim, profileState, id); break; } break; case AGHFP_INTERNAL_INIT_CFM: PRINT(("AGHFP_INTERNAL_INIT_CFM\n")); switch(profileState) { case aghfp_initialising: aghfpHandleInternalInitCfm(aghfp, (AGHFP_INTERNAL_INIT_CFM_T *) message); break; default: handleUnexpected(aghfpUnexpectedAghfpPrim, profileState, id); break; } break; /*************************************************************************/ /* SDP Messages */ /*************************************************************************/ case AGHFP_INTERNAL_SDP_REGISTER_CFM: PRINT(("AGHFP_INTERNAL_SDP_REGISTER_CFM\n")); switch(profileState) { case aghfp_initialising: aghfpHandleSdpInternalRegisterInit(aghfp, (AGHFP_INTERNAL_SDP_REGISTER_CFM_T *) message); break; case aghfp_ready: aghfpHandleSdpInternalRegisterCfm((AGHFP_INTERNAL_SDP_REGISTER_CFM_T *) message); break; default: handleUnexpected(aghfpUnexpectedAghfpPrim, profileState, id); break; } break; /*************************************************************************/ /* SLC Messages */ /*************************************************************************/ case AGHFP_INTERNAL_SLC_CONNECT_REQ: PRINT(("AGHFP_INTERNAL_SLC_CONNECT_REQ\n")); switch(profileState) { case aghfp_ready: aghfpHandleSlcConnectRequest(aghfp, (AGHFP_INTERNAL_SLC_CONNECT_REQ_T *) message); break; case aghfp_slc_connecting: case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: /* If this profile instance is already connecting/connected then reject the SLC connect request and inform the app. */ aghfpSendSlcConnectCfmToApp(aghfp_connect_failed_busy, aghfp); break; default: handleUnexpected(aghfpUnexpectedAghfpPrim, profileState, id); break; } break; case AGHFP_INTERNAL_SLC_CONNECT_RES: PRINT(("AGHFP_INTERNAL_SLC_CONNECT_RES\n")); switch(profileState) { case aghfp_slc_connecting: aghfpHandleSlcConnectResponse(aghfp, (AGHFP_INTERNAL_SLC_CONNECT_RES_T *) message); break; case aghfp_ready: case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: /* If the app is sending us an SLC connect response when we're not connecting then send it an error message since we currently don't have an SLC being established. */ aghfpSendSlcConnectCfmToApp(aghfp_connect_failed_busy, aghfp); break; default: handleUnexpected(aghfpUnexpectedAghfpPrim, profileState, id); break; } break; case AGHFP_INTERNAL_RFCOMM_CONNECT_REQ: PRINT(("AGHFP_INTERNAL_RFCOMM_CONNECT_REQ\n")); switch(profileState) { case aghfp_slc_connecting: aghfpHandleRfcommConnectRequest(aghfp, (AGHFP_INTERNAL_RFCOMM_CONNECT_REQ_T *) message); break; default: /* Something wrong, this message is sent internally from the AGHFP */ handleUnexpected(aghfpUnexpectedAghfpPrim, profileState, id); break; } break; case AGHFP_INTERNAL_SLC_DISCONNECT_REQ: PRINT(("AGHFP_INTERNAL_SLC_DISCONNECT_REQ")); switch(profileState) { case aghfp_slc_connecting: case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleSlcDisconnect(aghfp); break; case aghfp_ready: /* Send disconnect message with error - nothing to disconnect */ aghfpHandleDisconnectRequestFail(aghfp); break; case aghfp_initialising: default: handleUnexpected(aghfpUnexpectedAghfpPrim, profileState, id); break; } break; /*************************************************************************/ /* AT Messages */ /*************************************************************************/ case AGHFP_INTERNAL_AT_CKPD_CMD: PRINT(("AGHFP_INTERNAL_AT_CKPD_CMD\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleKeypadCommand(aghfp, ((AGHFP_INTERNAL_AT_CKPD_CMD_T*)message)->keycode); break; default: aghfpSendError(aghfp); break; } break; case AGHFP_INTERNAL_AT_BRSF_REQ: PRINT(("AGHFP_INTERNAL_AT_BRSF_REQ\n")); switch(profileState) { case aghfp_slc_connecting: { uint16 hf_supported_features = ((AGHFP_INTERNAL_AT_BRSF_REQ_T *)message)->hf_supported_features; /* Only allowed if we are an HFP device */ if (!supportedProfileIsHfp(aghfp->supported_profile)) Panic(); aghfpHandleBrsfRequest(aghfp, hf_supported_features); break; } default: aghfpSendError(aghfp); break; } break; case AGHFP_INTERNAL_AT_CIND_SUPPORTED_REQ: PRINT(("AGHFP_INTERNAL_AT_CIND_SUPPORTED_REQ\n")); switch(profileState) { case aghfp_slc_connecting: case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: /* Only allowed if we are an HFP device */ if (!supportedProfileIsHfp(aghfp->supported_profile)) Panic(); aghfpHandleCindSupportedRequest(aghfp); break; default: aghfpSendError(aghfp); break; } break; case AGHFP_INTERNAL_AT_CIND_STATUS_REQ: PRINT(("AGHFP_INTERNAL_AT_CIND_STATUS_REQ\n")); switch(profileState) { case aghfp_slc_connecting: case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: /* Only allowed if we are an HFP device */ if (!supportedProfileIsHfp(aghfp->supported_profile)) Panic(); aghfpHandleCindStatusRequest(aghfp); break; default: aghfpSendError(aghfp); break; } break; case AGHFP_INTERNAL_AT_CMER_REQ: PRINT(("AGHFP_INTERNAL_AT_CMER_REQ\n")); switch(profileState) { case aghfp_slc_connecting: { AGHFP_INTERNAL_AT_CMER_REQ_T *data = (AGHFP_INTERNAL_AT_CMER_REQ_T *)message; /* Only allowed if we are an HFP device */ if (!supportedProfileIsHfp(aghfp->supported_profile)) Panic(); aghfpHandleCmerRequest(aghfp, data->mode, data->ind); break; } default: aghfpSendError(aghfp); break; } break; case AGHFP_INTERNAL_CALL_HOLD_SUPPORT_REQ: /* HF sent AT+CHLD=? query */ PRINT(("AGHFP_INTERNAL_CALL_HOLD_SUPPORT_REQ\n")); switch(profileState) { case aghfp_slc_connecting: /* Only allowed if we are an HFP device */ if (!supportedProfileIsHfp(aghfp->supported_profile)) Panic(); aghfpHandleCallHoldSupportRequest(aghfp); break; default: aghfpSendError(aghfp); break; } break; case AGHFP_INTERNAL_CALL_HOLD_REQ: /* HF sent AT+CHLD=<action>[<idx>] instruction */ { AGHFP_INTERNAL_CALL_HOLD_REQ_T *msg = (AGHFP_INTERNAL_CALL_HOLD_REQ_T *)message; PRINT(("AGHFP_INTERNAL_CALL_HOLD_REQ\n")); switch(profileState) { case aghfp_active_call: aghfpHandleCallHoldReq(aghfp, msg->action, msg->index); break; default: aghfpSendError(aghfp); break; } break; } case AGHFP_INTERNAL_ANSWER_REQ: /* HF wants to answer the call */ PRINT(("AGHFP_INTERNAL_ANSWER_REQ\n")); switch(profileState) { case aghfp_incoming_call_establish: #if 0 /* Always pass notification to app and let it call AghfpCallAnswer() */ if ( aghfpCallManagerActive(aghfp) ) { aghfpSendOk(aghfp); aghfpManageCall(aghfp, CallEventAnswer, CallFlagOpenAudio); } else #endif { aghfpHandleAnswer(aghfp); } break; default: aghfpSendError(aghfp); break; } break; case AGHFP_INTERNAL_CALLER_ID_SETUP_REQ: /* HF wants to enable/disable caller ID notification */ PRINT(("AGHFP_INTERNAL_CALLER_ID_REQ\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleCallerIdSetupReq(aghfp, ((AGHFP_INTERNAL_CALLER_ID_SETUP_REQ_T*)message)->state); break; default: aghfpSendError(aghfp); break; } break; case AGHFP_INTERNAL_CALL_WAITING_SETUP_REQ: /* HF wants to enable/disable call waiting notification */ PRINT(("AGHFP_INTERNAL_CALL_WAITING_REQ\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleCallWaitingSetupReq(aghfp, ((AGHFP_INTERNAL_CALL_WAITING_SETUP_REQ_T*)message)->state); break; default: aghfpSendError(aghfp); break; } break; case AGHFP_INTERNAL_CALL_HANG_UP_REQ: /* HF wants to reject incoming call */ PRINT(("AGHFP_INTERNAL_CALL_HANG_UP_REQ\n")); switch(profileState) { case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: #if 0 /* Always pass notification up to app and let it call AghfpCallTerminate() */ if ( aghfpCallManagerActive(aghfp) ) { aghfpSendOk(aghfp); aghfpManageCall(aghfp, CallEventTerminate, CallFlagCloseAudio); } else #endif { aghfpHandleCallHangUpReq(aghfp); } break; default: aghfpSendError(aghfp); break; } break; case AGHFP_INTERNAL_DIAL_REQ: /* HF wants to dial a number */ PRINT (("AGHFP_INTERNAL_DIAL_REQ\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_active_call: { AGHFP_INTERNAL_DIAL_REQ_T *data = (AGHFP_INTERNAL_DIAL_REQ_T*)message; aghfpHandleDialReq(aghfp, data->number, data->size_number); break; } default: aghfpSendError(aghfp); break; } break; case AGHFP_INTERNAL_MEMORY_DIAL_REQ: /* HF wants to dial a number from the AG's phonebook */ PRINT (("AGHFP_INTERNAL_MEMORY_DIAL_REQ\n")); switch(profileState) { case aghfp_slc_connected: { AGHFP_INTERNAL_MEMORY_DIAL_REQ_T *data = (AGHFP_INTERNAL_MEMORY_DIAL_REQ_T*)message; aghfpHandleMemoryDialReq(aghfp, data->number, data->size_number); break; } default: aghfpSendError(aghfp); break; } break; case AGHFP_INTERNAL_LAST_NUMBER_REDIAL_REQ: /* HF wants to redial last number dialed by AG */ PRINT (("AGHFP_INTERNAL_LAST_NUMBER_REDIAL_REQ\n")); switch(profileState) { case aghfp_slc_connected: aghfpHandleLastNumberRedialReq(aghfp); break; default: aghfpSendError(aghfp); break; } break; case AGHFP_INTERNAL_NREC_SETUP_REQ: PRINT (("AGHFP_INTERNAL_NREC_SETUP_REQ\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleNrecSetupReq(aghfp, ((AGHFP_INTERNAL_NREC_SETUP_REQ_T*)message)->state); break; default: aghfpSendError(aghfp); break; } break; case AGHFP_INTERNAL_VOICE_RECOGNITION_SETUP_REQ: PRINT (("AGHFP_INTERNAL_VOICE_RECOGNITION_SETUP_REQ\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleVoiceRecognitionSetupReq(aghfp, ((AGHFP_INTERNAL_VOICE_RECOGNITION_SETUP_REQ_T*)message)->state); break; default: aghfpSendError(aghfp); break; } break; case AGHFP_INTERNAL_PHONE_NUMBER_REQ: PRINT (("AGHFP_INTERNAL_PHONE_NUMBER_REQ\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandlePhoneNumberForVoiceTagReq(aghfp); break; default: aghfpSendError(aghfp); break; } break; case AGHFP_INTERNAL_TRANSMIT_DTMF_CODE: { AGHFP_INTERNAL_TRANSMIT_DTMF_CODE_T *data = (AGHFP_INTERNAL_TRANSMIT_DTMF_CODE_T*)message; PRINT (("AGHFP_INTERNAL_TRANSMIT_DTMF_CODE\n")); switch(profileState) { case aghfp_active_call: aghfpHandleTransmitDtmfCode(aghfp, data->code); break; default: aghfpSendError(aghfp); break; } break; } case AGHFP_INTERNAL_RESPONSE_HOLD_STATUS_REQUEST_REQ: /* AT+BTRH? */ PRINT (("AGHFP_INTERNAL_RESPONSE_HOLD_STATUS_REQUEST_REQ\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleResponseHoldStatusRequest(aghfp); break; default: aghfpSendError(aghfp); break; } break; case AGHFP_INTERNAL_SET_RESPONSE_HOLD_STATUS_REQ: /* AT+BTRH=c */ { AGHFP_INTERNAL_SET_RESPONSE_HOLD_STATUS_REQ_T *msg = (AGHFP_INTERNAL_SET_RESPONSE_HOLD_STATUS_REQ_T *)message; PRINT (("AGHFP_INTERNAL_SET_RESPONSE_HOLD_STATUS_REQ\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleSetResponseHoldStatus(aghfp,msg->cmd); break; default: aghfpSendError(aghfp); break; } break; } case AGHFP_INTERNAL_SUBSCRIBER_NUMBER_REQ: /* AT+CNUM */ PRINT (("AGHFP_INTERNAL_SUBSCRIBER_NUMBER_REQ\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleSubscriberNumbersRequest(aghfp); break; default: aghfpSendError(aghfp); break; } break; case AGHFP_INTERNAL_CURRENT_CALLS_REQ: /* AT+CLCC */ PRINT (("AGHFP_INTERNAL_CURRENT_CALLS_REQ\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleCurrentCallsRequest(aghfp); break; default: aghfpSendError(aghfp); break; } break; case AGHFP_INTERNAL_NETWORK_OPERATOR_FORMAT_REQ: /* AT+COPS=m,f */ { AGHFP_INTERNAL_NETWORK_OPERATOR_FORMAT_REQ_T *msg = (AGHFP_INTERNAL_NETWORK_OPERATOR_FORMAT_REQ_T *)message; PRINT (("AGHFP_INTERNAL_NETWORK_OPERATOR_FORMAT_REQ\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleNetworkOperatorFormatRequest(aghfp, msg->mode, msg->format); break; default: aghfpSendError(aghfp); break; } break; } case AGHFP_INTERNAL_NETWORK_OPERATOR_REQ: /* AT+COPS? */ PRINT (("AGHFP_INTERNAL_NETWORK_OPERATOR_REQ\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleNetworkOperatorRequest(aghfp); break; default: aghfpSendError(aghfp); break; } break; /*************************************************************************/ /* Audio Connection Messages */ /*************************************************************************/ case AGHFP_INTERNAL_AUDIO_TRANSFER_REQ: /* TODO - really need to handle this message! */ break; case AGHFP_INTERNAL_AUDIO_CONNECT_REQ: PRINT(("AGHFP_INTERNAL_AUDIO_CONNECTION_REQ\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleAudioConnectReq(aghfp, (AGHFP_INTERNAL_AUDIO_CONNECT_REQ_T*)message); break; default: /* Panic in debug and ignore in release lib variants */ handleUnexpected(aghfpUnexpectedAghfpPrim, profileState, id); break; } break; case AGHFP_INTERNAL_AUDIO_CONNECT_RES: PRINT(("AGHFP_INTERNAL_AUDIO_CONNECT_RES\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: { aghfpHandleAudioConnectRes(aghfp, (AGHFP_INTERNAL_AUDIO_CONNECT_RES_T*)message); break; } default: /* Panic in debug and ignore in release lib variants */ handleUnexpected(aghfpUnexpectedAghfpPrim, profileState, id); break; } break; case AGHFP_INTERNAL_AUDIO_DISCONNECT_REQ: PRINT(("AGHFP_INTERNAL_AUDIO_DISCONNECT_REQ\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleAudioDisconnectReq(aghfp); break; default: /* Panic in debug and ignore in release lib variants */ handleUnexpected(aghfpUnexpectedAghfpPrim, profileState, id); break; } break; case AGHFP_INTERNAL_SET_AUDIO_PARAMS_REQ: PRINT(("AGHFP_INTERNAL_SET_AUDIO_PARAMS_REQ\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleSetAudioParamsReq(aghfp, (AGHFP_INTERNAL_SET_AUDIO_PARAMS_REQ_T*)message); break; default: /* Panic in debug and ignore in release lib variants */ handleUnexpected(aghfpUnexpectedAghfpPrim, profileState, id); break; } break; /*************************************************************************/ /* Indicator Messages */ /*************************************************************************/ case AGHFP_INTERNAL_SEND_SERVICE_INDICATOR: PRINT(("AGHFP_INTERNAL_SEND_SERVICE_INDICATOR\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: aghfpHandleSendServiceIndicator(aghfp, ((AGHFP_INTERNAL_SEND_SERVICE_INDICATOR_T*)message)->availability); break; default: aghfpSendCommonCfmMessageToApp(AGHFP_SEND_SERVICE_INDICATOR_CFM, aghfp, aghfp_fail); break; } break; case AGHFP_INTERNAL_SEND_CALL_INDICATOR: { aghfp_call_status status = ((AGHFP_INTERNAL_SEND_CALL_INDICATOR_T*)message)->status; PRINT(("AGHFP_INTERNAL_SEND_CALL_INDICATOR\n")); if ((profileState == aghfp_incoming_call_establish && status == aghfp_call_active) || (profileState == aghfp_outgoing_call_establish && status == aghfp_call_active) || (profileState == aghfp_active_call && status == aghfp_call_none)) { aghfpHandleSendCallIndicator(aghfp, status); } else { aghfpSendCommonCfmMessageToApp(AGHFP_SEND_CALL_INDICATOR_CFM, aghfp, aghfp_fail); } break; } case AGHFP_INTERNAL_SEND_CALL_SETUP_INDICATOR: { aghfp_call_setup_status status; status = ((AGHFP_INTERNAL_SEND_CALL_SETUP_INDICATOR_T*)message)->type; PRINT(("AGHFP_INTERNAL_SEND_CALL_SETUP_INDICATOR\n")); if ((profileState == aghfp_slc_connected && status == aghfp_call_setup_incoming) || (profileState == aghfp_slc_connected && status == aghfp_call_setup_outgoing) || (profileState == aghfp_incoming_call_establish && status == aghfp_call_setup_none) || (profileState == aghfp_outgoing_call_establish && status == aghfp_call_setup_none) || (profileState == aghfp_outgoing_call_establish && status == aghfp_call_setup_remote_alert) || (profileState == aghfp_active_call) ) { aghfpHandleSendCallSetupIndicator(aghfp, status); } else { aghfpSendCommonCfmMessageToApp(AGHFP_SEND_CALL_SETUP_INDICATOR_CFM, aghfp, aghfp_fail); } break; } case AGHFP_INTERNAL_SEND_CALL_HELD_INDICATOR: /* TODO - really need to handle this message */ break; case AGHFP_INTERNAL_SEND_SIGNAL_INDICATOR: /* TODO - really need to handle this message */ break; case AGHFP_INTERNAL_SEND_ROAM_INDICATOR: /* TODO - really need to handle this message */ break; case AGHFP_INTERNAL_SEND_BATT_CHG_INDICATOR: /* TODO - really need to handle this message */ break; case AGHFP_INTERNAL_SEND_CALL_WAITING_NOTIFICATION: { AGHFP_INTERNAL_SEND_CALL_WAITING_NOTIFICATION_T *scwn = (AGHFP_INTERNAL_SEND_CALL_WAITING_NOTIFICATION_T *)message; PRINT(("AGHFP_INTERNAL_SEND_CALL_WAITING_NOTIFICATION\n")); switch(profileState) { case aghfp_active_call: aghfpHandleSendCallWaitingNotification(aghfp, scwn->type, scwn->size_number, scwn->number, scwn->size_string, scwn->string); break; default: free(scwn->string); aghfpSendCommonCfmMessageToApp(AGHFP_SEND_CALL_WAITING_NOTIFICATION_CFM, aghfp, aghfp_fail); break; } break; } case AGHFP_INTERNAL_SET_SERVICE_STATE: { PRINT(("AGHFP_INTERNAL_SET_SERVICE_STATE\n")); switch (profileState) { case aghfp_initialising: break; /* Silently ignore */ case aghfp_ready: case aghfp_slc_connecting: case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleSetServiceState(aghfp, ((AGHFP_INTERNAL_SET_SERVICE_STATE_T*)message)->service_state); break; } break; } /*************************************************************************/ /* Call Related Messages */ /*************************************************************************/ case AGHFP_INTERNAL_SEND_RING_ALERT: PRINT(("AGHFP_INTERNAL_SEND_RING_ALERT\n")); switch(profileState) { case aghfp_incoming_call_establish: aghfpHandleSendRingAlert(aghfp); break; default: aghfpSendCommonCfmMessageToApp(AGHFP_SEND_RING_ALERT_CFM, aghfp, aghfp_fail); break; } break; case AGHFP_INTERNAL_SEND_CALLER_ID: { AGHFP_INTERNAL_SEND_CALLER_ID_T *msg = (AGHFP_INTERNAL_SEND_CALLER_ID_T*)message; switch(profileState) { case aghfp_incoming_call_establish: aghfpHandleSendCallerId(aghfp, msg->type, msg->size_number, msg->size_string, msg->data); break; default: aghfpSendCommonCfmMessageToApp(AGHFP_SEND_CALLER_ID_CFM, aghfp, aghfp_fail); break; } break; } case AGHFP_INTERNAL_INBAND_RING_TONE_ENABLE: PRINT(("AGHFP_INTERNAL_INBAND_RING_TONE_ENABLE\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: aghfpHandleInBandRingToneEnable(aghfp, ((AGHFP_INTERNAL_INBAND_RING_TONE_ENABLE_T*)message)->enable); break; default: aghfpSendCommonCfmMessageToApp(AGHFP_INBAND_RING_ENABLE_CFM, aghfp, aghfp_fail); break; } break; /*************************************************************************/ /* Call Management Messages */ /*************************************************************************/ case AGHFP_INTERNAL_CALL_MGR_CREATE_REQ: PRINT(("AGHFP_INTERNAL_CALL_MGR_CREATE_REQ\n")); switch(profileState) { case aghfp_slc_connected: aghfpHandleCallCreate(aghfp, (AGHFP_INTERNAL_CALL_MGR_CREATE_REQ_T *)message); break; default: aghfpSendCallCreateCfmToApp(aghfp, aghfp_call_create_error); break; } break; case AGHFP_INTERNAL_CALL_MGR_CREATE_WITH_AUDIO_REQ: PRINT(("AGHFP_INTERNAL_CALL_MGR_CREATE_WITH_AUDIO_REQ\n")); switch(profileState) { case aghfp_slc_connected: aghfpHandleCallCreateAudio(aghfp, (AGHFP_INTERNAL_CALL_MGR_CREATE_WITH_AUDIO_REQ_T *)message); break; default: aghfpSendCallCreateCfmToApp(aghfp, aghfp_call_create_error); break; } break; case AGHFP_INTERNAL_CALL_MGR_ANSWER_REQ: PRINT(("AGHFP_INTERNAL_CALL_MGR_ANSWER_REQ\n")); switch(profileState) { case aghfp_incoming_call_establish: aghfpHandleCallAnswer(aghfp); break; default: /* Silently ignore message */ break; } break; case AGHFP_INTERNAL_CALL_MGR_REMOTE_ANSWERED_REQ: PRINT(("AGHFP_INTERNAL_CALL_MGR_REMOTE_ANSWERED_REQ\n")); switch(profileState) { case aghfp_outgoing_call_establish: aghfpHandleCallRemoteAnswered(aghfp); break; default: /* Silently ignore message */ break; } break; case AGHFP_INTERNAL_CALL_MGR_TERMINATE_REQ: PRINT(("AGHFP_INTERNAL_CALL_MGR_TERMINATE_REQ\n")); switch(profileState) { case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleCallTerminate(aghfp, (AGHFP_INTERNAL_CALL_MGR_TERMINATE_REQ_T *)message); break; default: aghfpSendCommonCfmMessageToApp(AGHFP_CALL_MGR_TERMINATE_IND, aghfp, aghfp_fail); break; } break; case AGHFP_INTERNAL_RING_REPEAT_REQ: PRINT(("AGHFP_INTERNAL_RING_REPEAT_REQ\n")); switch(profileState) { case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: aghfpManageCall(aghfp, CallEventRing, CallFlagsNone); break; default: /* Silently ignore message */ break; } break; /*************************************************************************/ /* Misc Other Messages */ /*************************************************************************/ case AGHFP_INTERNAL_SET_CALLER_ID_DETAILS_REQ: PRINT(("AGHFP_INTERNAL_SET_CALLER_ID_DETAILS_REQ\n")); switch(profileState) { case aghfp_initialising: case aghfp_ready: case aghfp_slc_connecting: case aghfp_slc_connected: aghfpHandleSetCallerIdDetails(aghfp, (AGHFP_INTERNAL_SET_CALLER_ID_DETAILS_REQ_T *)message); break; default: aghfpSendCommonCfmMessageToApp(AGHFP_SET_CALLER_ID_DETAILS_CFM, aghfp, aghfp_fail); break; } break; case AGHFP_INTERNAL_VOICE_RECOGNITION_ENABLE: PRINT(("AGHFP_INTERNAL_VOICE_RECOGNITION_ENABLE\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleVoiceRecognitionEnable(aghfp, ((AGHFP_INTERNAL_VOICE_RECOGNITION_ENABLE_T*)message)->enable); break; default: aghfpSendCommonCfmMessageToApp(AGHFP_VOICE_RECOGNITION_ENABLE_CFM, aghfp, aghfp_fail); } break; case AGHFP_INTERNAL_SEND_PHONE_NUMBER_FOR_VOICE_TAG: { AGHFP_INTERNAL_SEND_PHONE_NUMBER_FOR_VOICE_TAG_T *data; data = (AGHFP_INTERNAL_SEND_PHONE_NUMBER_FOR_VOICE_TAG_T *)message; PRINT(("AGHFP_INTERNAL_SEND_PHONE_NUMBER_FOR_VOICE_TAG\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleSendPhoneNumberForVoiceTag(aghfp, data->size_number, data->number); break; default: aghfpSendCommonCfmMessageToApp(AGHFP_SEND_PHONE_NUMBER_FOR_VOICE_TAG_CFM, aghfp, aghfp_fail); } break; } case AGHFP_INTERNAL_SET_REMOTE_MICROPHONE_GAIN: PRINT(("AGHFP_INTERNAL_SET_REMOTE_MICROPHONE_GAIN\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleSetRemoteMicrophoneGain(aghfp, ((AGHFP_INTERNAL_SET_REMOTE_MICROPHONE_GAIN_T*)message)->gain); break; default: aghfpSendCommonCfmMessageToApp(AGHFP_SET_REMOTE_MICROPHONE_GAIN_CFM, aghfp, aghfp_fail); } break; case AGHFP_INTERNAL_SET_REMOTE_SPEAKER_VOLUME: PRINT(("AGHFP_INTERNAL_SET_REMOTE_SPEAKER_VOLUME\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleSetRemoteSpeakerVolume(aghfp, ((AGHFP_INTERNAL_SET_REMOTE_SPEAKER_VOLUME_T*)message)->volume); break; default: aghfpSendCommonCfmMessageToApp(AGHFP_SET_REMOTE_SPEAKER_VOLUME_CFM, aghfp, aghfp_fail); } break; case AGHFP_INTERNAL_SYNC_MIC_GAIN: PRINT(("AGHFP_INTERNAL_SYNC_MIC_GAIN\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleSyncMicrophoneGain(aghfp, ((AGHFP_INTERNAL_SYNC_MIC_GAIN_T*)message)->gain); break; default: /* We've received a mic gain command from the HF, but we haven't currently got an SLC. That can't really happen. If it does, then just silently ignore. */ break; } break; case AGHFP_INTERNAL_SYNC_SPEAKER_VOLUME: PRINT(("AGHFP_INTERNAL_SYNC_SPEAKER_VOLUME\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleSyncSpeakerVolume(aghfp, ((AGHFP_INTERNAL_SYNC_SPEAKER_VOLUME_T*)message)->volume); break; default: /* We've received a speaker gain command from the HF, but we haven't currently got an SLC. That can't really happen. If it does, then just silently ignore. */ break; } break; case AGHFP_INTERNAL_SEND_RESPONSE_HOLD_STATE: PRINT(("AGHFP_INTERNAL_SEND_RESPONSE_HOLD_STATE\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleSendResponseHoldState(aghfp, ((AGHFP_INTERNAL_SEND_RESPONSE_HOLD_STATE_T*)message)->state); break; default: /* We've received a command from the HF, but we haven't currently got an SLC. That can't really happen. If it does, then just silently ignore. */ break; } break; case AGHFP_INTERNAL_CONFIRM_RESPONSE_HOLD_STATE: PRINT(("AGHFP_INTERNAL_CONFIRM_RESPONSE_HOLD_STATE\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleConfirmResponseHoldState(aghfp, ((AGHFP_INTERNAL_CONFIRM_RESPONSE_HOLD_STATE_T*)message)->state); break; default: /* We've received a command from the HF, but we haven't currently got an SLC. That can't really happen. If it does, then just silently ignore. */ break; } break; case AGHFP_INTERNAL_SEND_SUBSCRIBER_NUMBER: PRINT(("AGHFP_INTERNAL_SEND_SUBSCRIBER_NUMBER\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleSendSubscriberNumber(aghfp, (AGHFP_INTERNAL_SEND_SUBSCRIBER_NUMBER_T*)message); break; default: /* We've received a command from the HF, but we haven't currently got an SLC. That can't really happen. If it does, then just silently ignore. */ break; } break; case AGHFP_INTERNAL_SEND_SUBSCRIBER_NUMBERS_COMPLETE: PRINT(("AGHFP_INTERNAL_SEND_SUBSCRIBER_NUMBERS_COMPLETE\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleSendSubscriberNumbersComplete(aghfp); break; default: /* We've received a command from the HF, but we haven't currently got an SLC. That can't really happen. If it does, then just silently ignore. */ break; } break; case AGHFP_INTERNAL_SEND_CURRENT_CALL: PRINT(("AGHFP_INTERNAL_SEND_CURRENT_CALL\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleSendCurrentCall(aghfp, (AGHFP_INTERNAL_SEND_CURRENT_CALL_T*)message); break; default: /* We've received a command from the HF, but we haven't currently got an SLC. That can't really happen. If it does, then just silently ignore. */ break; } break; case AGHFP_INTERNAL_SEND_CURRENT_CALLS_COMPLETE: PRINT(("AGHFP_INTERNAL_SEND_CURRENT_CALLS_COMPLETE\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleSendCurrentCallsComplete(aghfp); break; default: /* We've received a command from the HF, but we haven't currently got an SLC. That can't really happen. If it does, then just silently ignore. */ break; } break; case AGHFP_INTERNAL_SEND_NETWORK_OPERATOR: { AGHFP_INTERNAL_SEND_NETWORK_OPERATOR_T *msg = (AGHFP_INTERNAL_SEND_NETWORK_OPERATOR_T*)message; PRINT(("AGHFP_INTERNAL_SEND_NETWORK_OPERATOR\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleSendNetworkOperator(aghfp, msg->mode, msg->size_operator, msg->operator); break; default: /* We've received a command from the HF, but we haven't currently got an SLC. That can't really happen. If it does, then just silently ignore. */ break; } break; } case AGHFP_INTERNAL_USER_DATA_REQ: PRINT(("AGHFP_INTERNAL_USER_DATA_REQ\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: aghfpHandleUserDataReq(aghfp, (AGHFP_INTERNAL_USER_DATA_REQ_T *) message); break; case aghfp_ready: case aghfp_slc_connecting: /* Cannot send the data, haven't got a valid SLC established */ aghfpHandleUserDataReqFail(aghfp, (AGHFP_INTERNAL_USER_DATA_REQ_T *) message); break; case aghfp_initialising: default: /* We have received a request to send user data and we're in the wrong state */ break; } break; case AGHFP_INTERNAL_SEND_ERROR_REQ: PRINT(("AGHFP_INTERNAL_SEND_ERROR_REQ\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: case aghfp_slc_connecting: aghfpSendError(aghfp); break; case aghfp_ready: /* Cannot send error, haven't got a valid RFCOMM established */ aghfpSendCommonCfmMessageToApp(AGHFP_SEND_ERROR_CFM, aghfp, aghfp_fail); break; case aghfp_initialising: default: /* We have received this request in the wrong state */ break; } break; case AGHFP_INTERNAL_SEND_OK_REQ: PRINT(("AGHFP_INTERNAL_SEND_OK_REQ\n")); switch(profileState) { case aghfp_slc_connected: case aghfp_incoming_call_establish: case aghfp_outgoing_call_establish: case aghfp_active_call: case aghfp_slc_connecting: aghfpSendOk(aghfp); break; case aghfp_ready: /* Cannot send error, haven't got a valid RFCOMM established */ aghfpSendCommonCfmMessageToApp(AGHFP_SEND_OK_CFM, aghfp, aghfp_fail); break; case aghfp_initialising: default: /* We have received this request in the wrong state */ break; } break; /* WB-Speech Messages */ case AGHFP_INTERNAL_WBS_CODEC_NEGOTIATE_REQ: PRINT(("AGHFP_INTERNAL_WBS_CODEC_NEGOTIATE_REQ\n")); aghfpHandleWbsCodecNegReq(aghfp, ((AGHFP_INTERNAL_WBS_CODEC_NEGOTIATE_REQ_T*)message)->codec); break; case AGHFP_INTERNAL_WBS_CODEC_CONNECTION_REQ: PRINT(("AGHFP_INTERNAL_WBS_CODEC_CONNECTION_REQ\n")); aghfpHandleWbsCodecConReq(aghfp); break; case AGHFP_INTERNAL_CODEC_NEGOTIATION_REQ: PRINT(("AGHFP_INTERNAL_CODEC_NEGOTIATION_REQ\n")); aghfpHandleCodecNegotiationReq(aghfp, (AGHFP_INTERNAL_CODEC_NEGOTIATION_REQ_T*)message); break; default: PRINT(("Unhandled message\n")); /* Received an unhandled message */ handleUnexpected(aghfpUnexpectedMessage, profileState, id); break; } }
static void manageCallWaitResponse (AGHFP *aghfp, aghfp_call_event call_event, aghfp_call_flags call_flags) { switch ( call_event ) { case CallEventCreate: break; case CallEventAnswer: case CallEventRemoteAnswered: setCallFlags(aghfp, call_flags | CallFlagResponded); if ( !usingHsp(aghfp) && aghfp->audio_connection_state != aghfp_audio_codec_connect) /* Do not resend the call indicator info if we got here from a WBS codec negotiation */ { /* Working in HFP mode */ /* Call is now setup even though we might not have an audio channel */ aghfpSendCallIndicator(aghfp, aghfp_call_active); aghfpSendCallSetupIndicator(aghfp, aghfp_call_setup_none); } if ( checkCallFlag(aghfp, CallFlagCloseAudio) ) { /* Use CloseAudio flag to shutdown any existing audio channel or prevent one being created */ clearCallFlags(aghfp, CallFlagOpenAudio | CallFlagCloseAudio); if ( haveAudio(aghfp) ) { /* Audio disconnected event will be picked up in CallConnected state */ aghfpAudioDisconnectRequest(aghfp); } } if ( checkCallFlag(aghfp, CallFlagOpenAudio) && !haveAudio(aghfp)) { clearCallFlags(aghfp, CallFlagOpenAudio); aghfpAudioConnectRequest(aghfp); /* Check to see if aghfpAudioConnectRequest resulted in the commencement of a WBS negotiation */ if(aghfp->audio_connection_state != aghfp_audio_codec_connect) { /* Only move to the CallProgressWaitAudioOpen state if a WBS negotiation has not been started. */ setCallProgress(aghfp, CallProgressWaitAudioOpen); } } else { setCallProgress(aghfp, CallProgressComplete); aghfpSetState(aghfp, aghfp_active_call); aghfpSendCallCreateCfmToApp(aghfp, aghfp_call_create_success); } break; case CallEventTerminate: setCallFlags(aghfp, call_flags & (CallFlagsAll)); if ( checkCallFlag(aghfp, CallFlagCloseAudio) && haveAudio(aghfp) ) { aghfpAudioDisconnectRequest(aghfp); setCallProgress(aghfp, CallProgressWaitAudioCancel); } else { if ( !usingHsp(aghfp) ) { /* Working in HFP mode */ aghfpSendCallSetupIndicator(aghfp, aghfp_call_setup_none); } setCallProgress(aghfp, CallProgressIdle); aghfpSetState(aghfp, aghfp_slc_connected); aghfpSendCallCreateCfmToApp(aghfp, aghfp_call_create_aborted); } break; case CallEventTerminateHeld: /* duplicate of CallEventTerminate but without the aghfpSendCallSetupIndicator */ setCallFlags(aghfp, CallFlagCloseAudio); setCallProgress(aghfp, CallProgressIdle); aghfpSetState(aghfp, aghfp_slc_connected); aghfpSendCallCreateCfmToApp(aghfp, aghfp_call_create_aborted); break; case CallEventAcceptHeld: /*duplicate of CallEventAnswer but without the aghfpSendCallIndicator and aghfpSendCallSetupIndicator */ /* still need to change aghfp state */ setCallFlags(aghfp, call_flags | CallFlagResponded); aghfpSetState(aghfp, aghfp_active_call); /* Use CloseAudio flag to shutdown any existing audio channel or prevent one being created */ clearCallFlags(aghfp, CallFlagOpenAudio | CallFlagCloseAudio); if ( haveAudio(aghfp) ) { /* Audio disconnected event will be picked up in CallConnected state */ aghfpAudioDisconnectRequest(aghfp); } setCallProgress(aghfp, CallProgressComplete); aghfpSetState(aghfp, aghfp_active_call); aghfpSendCallCreateCfmToApp(aghfp, aghfp_call_create_success); break; case CallEventAudioConnected: case CallEventAudioDisconnected: case CallEventAudioTransfer: break; case CallEventRing: sendRingNotifications(aghfp); break; case CallEventSlcRemoved: /* SLC has been removed */ setCallProgress(aghfp, CallProgressIdle); aghfpSetState(aghfp, aghfp_ready); aghfpSendCallCreateCfmToApp(aghfp, aghfp_call_create_slc_removed); aghfpSendSlcDisconnectIndToApp(aghfp, convertCallFlagToDisconnectStatus(call_flags)); break; default: Panic(); } }
static void manageCallWaitAudioOpen (AGHFP *aghfp, aghfp_call_event call_event, aghfp_call_flags call_flags) { switch ( call_event ) { case CallEventCreate: case CallEventAnswer: case CallEventRemoteAnswered: break; case CallEventTerminate: /* Queue up call terminate request until audio connect completes */ setCallFlags(aghfp, call_flags | CallFlagTerminate); break; case CallEventAudioConnected: setCallFlags(aghfp, call_flags & (CallFlagsAll)); if ( !checkCallFlag(aghfp, CallFlagSuccess) ) { /* Audio connect failed */ if ( !usingHsp(aghfp) ) { aghfpSendCallIndicator(aghfp, aghfp_call_none); aghfpSendCallSetupIndicator(aghfp, aghfp_call_setup_none); } setCallProgress(aghfp, CallProgressIdle); aghfpSetState(aghfp, aghfp_slc_connected); aghfpSendCallCreateCfmToApp(aghfp, aghfp_call_create_failure); } else if ( checkCallFlag(aghfp, CallFlagTerminate) ) { /* Call terminate request has been made */ clearCallFlags(aghfp, CallFlagTerminate); if ( haveAudio(aghfp) && checkCallFlag(aghfp, CallFlagCloseAudio) ) { /* Shut down audio connection */ clearCallFlags(aghfp, CallFlagCloseAudio); aghfpAudioDisconnectRequest(aghfp); setCallProgress(aghfp, CallProgressWaitAudioCancel); } else { /* Either audio connection does not exist or it is to remain open */ if ( !usingHsp(aghfp) ) { aghfpSendCallIndicator(aghfp, aghfp_call_none); aghfpSendCallSetupIndicator(aghfp, aghfp_call_setup_none); } setCallProgress(aghfp, CallProgressIdle); aghfpSetState(aghfp, aghfp_slc_connected); aghfpSendCallCreateCfmToApp(aghfp, aghfp_call_create_aborted); } } else if ( checkCallFlag(aghfp, CallFlagResponseReqd) ) { if ( checkCallFlag(aghfp, CallFlagRingAlertsReqd) ) { sendRingNotifications(aghfp); } clearCallFlags(aghfp, CallFlagResponseReqd); sendCallCreateWaitingIndToApp(aghfp); setCallProgress(aghfp, CallProgressWaitResponse); } else { /* Call setup is now complete */ if ( !checkCallFlag(aghfp, CallFlagResponded) && !usingHsp(aghfp) ) { aghfpSendCallIndicator(aghfp, aghfp_call_active); aghfpSendCallSetupIndicator(aghfp, aghfp_call_setup_none); } clearCallFlags(aghfp, CallFlagsAll); setCallProgress(aghfp, CallProgressComplete); aghfpSetState(aghfp, aghfp_active_call); aghfpSendCallCreateCfmToApp(aghfp, aghfp_call_create_success); } break; case CallEventAudioDisconnected: case CallEventAudioTransfer: case CallEventRing: case CallEventTerminateHeld: case CallEventAcceptHeld: break; case CallEventSlcRemoved: /* SLC has been removed */ setCallProgress(aghfp, CallProgressIdle); aghfpSetState(aghfp, aghfp_ready); aghfpSendCallCreateCfmToApp(aghfp, aghfp_call_create_slc_removed); aghfpSendSlcDisconnectIndToApp(aghfp, convertCallFlagToDisconnectStatus(call_flags)); break; default: Panic(); } }
static void manageCallIdle (AGHFP *aghfp, aghfp_call_event call_event, aghfp_call_flags call_flags) { switch ( call_event ) { case CallEventCreate: clearCallFlags(aghfp, CallFlagsAll); setCallFlags(aghfp, call_flags & (CallFlagsAll)); switch (aghfp->call_params.call_type) { case aghfp_call_type_incoming: /* Always require a response and ring indications for this type of call */ setCallFlags(aghfp, CallFlagResponseReqd | CallFlagRingAlertsReqd); if ( usingHsp(aghfp) ) { /* Working in HSP mode */ /* HSP mandates that audio must be present */ setCallFlags(aghfp, CallFlagOpenAudio); /* B-11840: what if audio params are unspecified? */ if ( inbandSupported(aghfp) ) { /* Ensure audio exists before an answer call response is actioned */ setCallFlags(aghfp, CallFlagResponseAfterAudio); } } else { /* Working in HFP mode */ aghfpSendCallSetupIndicator(aghfp, aghfp_call_setup_incoming); if ( inbandSupported(aghfp) && (haveAudio(aghfp) || checkCallFlag(aghfp, CallFlagOpenAudio)) ) { setCallFlags(aghfp, CallFlagResponseAfterAudio); aghfpSendInBandRingToneEnable(aghfp, TRUE); } else { aghfpSendInBandRingToneEnable(aghfp, FALSE); } } aghfpSetState(aghfp, aghfp_incoming_call_establish); break; case aghfp_call_type_outgoing: /* Always require a response, but not ring alerts, for this type of call */ setCallFlags(aghfp, CallFlagResponseReqd | CallFlagResponseAfterAudio); clearCallFlags(aghfp, CallFlagRingAlertsReqd); aghfpSendCallSetupIndicator(aghfp, aghfp_call_setup_outgoing); if ( haveAudio(aghfp) || !checkCallFlag(aghfp, CallFlagOpenAudio) ) { aghfpSendCallSetupIndicator(aghfp, aghfp_call_setup_remote_alert); } aghfpSetState(aghfp, aghfp_outgoing_call_establish); break; case aghfp_call_type_transfer: /* Never require a response or ring alerts for this type of call */ clearCallFlags(aghfp, CallFlagResponseReqd | CallFlagResponseAfterAudio | CallFlagRingAlertsReqd); if ( usingHsp(aghfp) ) { /* Working in HSP mode */ /* HSP mandates that audio must be present */ setCallFlags(aghfp, CallFlagOpenAudio); /* B-11840: what if audio params are unspecified? */ } else { /* Working in HFP mode */ /* Call is now setup even though we might not have an audio channel */ } break; } if ( !haveAudio(aghfp) && checkCallFlag(aghfp, CallFlagOpenAudio) && !(checkCallFlag(aghfp, CallFlagResponseReqd) && !checkCallFlag(aghfp, CallFlagResponseAfterAudio)) ) { /* Open an audio channel */ clearCallFlags(aghfp, CallFlagOpenAudio); if ( usingHsp(aghfp) && checkCallFlag(aghfp, CallFlagRingAlertsReqd) ) { sendRingNotifications(aghfp); } aghfpAudioConnectRequest(aghfp); /* Check to see if aghfpAudioConnectRequest resulted in the commencement of a WBS negotiation */ if(aghfp->audio_connection_state != aghfp_audio_codec_connect) { /* Only move to the CallProgressWaitAudioOpen state if a WBS negotiation has not been started. */ setCallProgress(aghfp, CallProgressWaitAudioOpen); } } else if ( checkCallFlag(aghfp, CallFlagResponseReqd) && !(checkCallFlag(aghfp, CallFlagOpenAudio) && checkCallFlag(aghfp, CallFlagResponseAfterAudio)) ) { /* Wait for a repsonse from remote end */ clearCallFlags(aghfp, CallFlagResponseReqd); if ( checkCallFlag(aghfp, CallFlagRingAlertsReqd) ) { sendRingNotifications(aghfp); } sendCallCreateWaitingIndToApp(aghfp); setCallProgress(aghfp, CallProgressWaitResponse); } else { /* Call setup is complete */ aghfpSendCallIndicator(aghfp, aghfp_call_active); aghfpSendCallSetupIndicator(aghfp, aghfp_call_setup_none); setCallProgress(aghfp, CallProgressComplete); aghfpSetState(aghfp, aghfp_active_call); aghfpSendCallCreateCfmToApp(aghfp, aghfp_call_create_success); } break; case CallEventAnswer: case CallEventRemoteAnswered: case CallEventTerminate: case CallEventTerminateHeld: case CallEventAcceptHeld: case CallEventAudioConnected: case CallEventAudioDisconnected: case CallEventAudioTransfer: case CallEventRing: break; case CallEventSlcRemoved: /* SLC has been removed */ setCallProgress(aghfp, CallProgressIdle); aghfpSetState(aghfp, aghfp_ready); aghfpSendSlcDisconnectIndToApp(aghfp, convertCallFlagToDisconnectStatus(call_flags)); break; default: Panic(); } }