/**************************************************************************** NAME aghfpHandleSyncDisconnectInd DESCRIPTION Audio (Synchronous) connection has been disconnected RETURNS void */ void aghfpHandleSyncDisconnectInd(AGHFP *aghfp, const CL_DM_SYNC_DISCONNECT_IND_T *ind) { /* If it's not our sink, silently ignore this indication */ if ( ind->audio_sink == aghfp->audio_sink ) { if ( aghfp->audio_connection_state==aghfp_audio_connected || aghfp->audio_connection_state==aghfp_audio_disconnecting ) { /* Inform the app */ if (ind->status == hci_success) { resetAudioParams(aghfp); aghfp->audio_connection_state = aghfp_audio_disconnected; if ( aghfpCallManagerActiveNotComplete(aghfp) ) { aghfpManageCall(aghfp, CallEventAudioDisconnected, CallFlagSuccess); } else { sendAudioDisconnectIndToApp(aghfp, aghfp_success); } } else { /* Disconnect has failed, we are still connected - inform the app */ if ( aghfpCallManagerActiveNotComplete(aghfp) ) { aghfpManageCall(aghfp, CallEventAudioDisconnected, CallFlagFail); } else { sendAudioDisconnectIndToApp(aghfp, aghfp_fail); } } /* Update the local state. Check current state in case SLC disconnect has beaten the SCO/eSCO disconnect */ if (!aghfpCallManagerActive(aghfp) && supportedProfileIsHsp(aghfp->supported_profile) && (aghfp->state != aghfp_ready)) { aghfpSetState(aghfp, aghfp_slc_connected); } } else { /* Should never get here */ AGHFP_DEBUG(("aghfpHandleSyncDisconnectInd invalid state %d\n",aghfp->audio_connection_state)); } } }
/**************************************************************************** Profile handler function called in response to issuing an AGHFP_INTERNAL_CALL_MGR_REMOTE_ANSWERED_REQ message. */ void aghfpHandleCallRemoteAnswered (AGHFP *aghfp) { if ( aghfp->call_progress==CallProgressWaitResponse && aghfp->call_params.call_type==aghfp_call_type_outgoing ) { aghfpManageCall(aghfp, CallEventRemoteAnswered, CallFlagsNone); } }
/**************************************************************************** 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); } }
/**************************************************************************** Profile handler function called in response to issuing an AGHFP_INTERNAL_CALL_MGR_TERMINATE_REQ message. */ void aghfpHandleHeldCallAccept (AGHFP *aghfp) { if ( aghfp->call_progress!=CallProgressIdle ) { aghfpManageCall(aghfp, CallEventAcceptHeld, CallFlagCloseAudio); } }
/**************************************************************************** Profile handler function called in response to issuing an AGHFP_INTERNAL_CALL_MGR_TERMINATE_REQ message. */ void aghfpHandleHeldCallTerminate (AGHFP *aghfp) { if ( aghfp->call_progress!=CallProgressIdle ) { aghfpManageCall(aghfp, CallEventTerminateHeld, CallFlagsNone); } }
/**************************************************************************** Profile handler function called in response to issuing an AGHFP_INTERNAL_CALL_MGR_TERMINATE_REQ message. */ void aghfpHandleCallTerminate (AGHFP *aghfp, AGHFP_INTERNAL_CALL_MGR_TERMINATE_REQ_T *req) { if ( aghfp->call_progress!=CallProgressIdle ) { aghfpManageCall(aghfp, CallEventTerminate, (req->keep_sink)?CallFlagsNone:CallFlagCloseAudio); } }
/**************************************************************************** Profile handler function called in response to issuing an AGHFP_INTERNAL_CALL_MGR_ANSWER_REQ message. */ void aghfpHandleCallAnswer (AGHFP *aghfp) { /* B-11839: should validate parameters here? */ if ( aghfp->call_progress==CallProgressWaitResponse && aghfp->call_params.call_type==aghfp_call_type_incoming ) { /* Call being answered at AG, close any existing audio link to HS */ aghfpManageCall(aghfp, CallEventAnswer, CallFlagCloseAudio); } }
/**************************************************************************** Handle RFCOMM disconnection */ static void aghfpHandleRfcommDisconnect(AGHFP *aghfp, rfcomm_disconnect_status status) { if ( aghfpCallManagerActive(aghfp) ) { /* Inform Call Manager */ aghfpManageCall(aghfp, CallEventSlcRemoved, aghfpConvertDisconnectStatusToCallFlag(convertRfcommDisconnectStatus(status))); } else { /* Convert the rfc disconnect status into its aghfp counterpart and send to app */ aghfpSendSlcDisconnectIndToApp(aghfp, convertRfcommDisconnectStatus(status)); } }
/**************************************************************************** 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); } }
/* Handle Codec Connection request from the HF (AT+BCC). This function performs the the actual actions of handling the AT+BCC (once the audio params have been obtained from the app, i.e. after aghfpHandleWbsCodecConReq() and ). */ static void aghfpHandleWbsCodecConReqProcessing(AGHFP *aghfp) { /* Are we supporting WBS */ if (aghfp->use_wbs) { /* OK to initiate WBS Codec Negotiation. */ /* Send OK */ aghfpSendOk(aghfp); /* If we haven't negotiatied a codec we need to do so. If we have, we're gonna go ahead and use it here. */ if (aghfp->use_codec == 0) { /* Start codec negotiation with HF. */ if (aghfpWbsStartCodecNegotiation(aghfp, aghfp_negotiate_audio_at_hf)) { aghfp->audio_connection_state = aghfp_audio_codec_connect; } } else { if (!aghfpCallManagerActiveNotComplete(aghfp)) { MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_AUDIO_CONNECT_REQ); AGHFP_DEBUG((" Normal Audio Connection\n")); message->audio_params = aghfp->audio_params; message->packet_type = aghfp->audio_packet_type; MessageSend(&aghfp->task, AGHFP_INTERNAL_AUDIO_CONNECT_REQ, message); } else { /* Save the audio packet type for Call Manager */ aghfpStoreAudioParams(aghfp, aghfp->audio_packet_type, &aghfp->audio_params); /* Answer the call again now that the WBS negotiation is complete. */ aghfpManageCall(aghfp, CallEventAnswer, CallFlagOpenAudio); } } } else { /* WBS not supported, send ERROR. */ aghfpSendError(aghfp); } }
void AghfpStartAudioAfterAppCodecNegotiation(AGHFP * aghfp) { if (!aghfpCallManagerActiveNotComplete(aghfp)) { MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_AUDIO_CONNECT_REQ); AGHFP_DEBUG((" Normal Audio Connection\n")); /* Assume that the audio parameters have been previously stored using aghfpStoreAudioParams() */ message->audio_params = aghfp->audio_params; message->packet_type = aghfp->audio_packet_type; MessageSend(&aghfp->task, AGHFP_INTERNAL_AUDIO_CONNECT_REQ, message); } else { /* Answer the call again now that the WBS negotiation is complete. */ aghfpManageCall(aghfp, CallEventAnswer, CallFlagOpenAudio); } }
/**************************************************************************** NAME aghfpHandleSyncConnectCfm DESCRIPTION Confirmation in response to an audio (SCO/eSCO) open request indicating the outcome of the Synchronous connect attempt. RETURNS void */ void aghfpHandleSyncConnectCfm(AGHFP *aghfp, const CL_DM_SYNC_CONNECT_CFM_T *cfm) { if ( aghfp->audio_connection_state==aghfp_audio_connecting_esco || aghfp->audio_connection_state==aghfp_audio_connecting_sco || aghfp->audio_connection_state==aghfp_audio_accepting ) { /* Informs us of the outcome of the Synchronous connect attempt */ if (cfm->status == hci_success) { /* store the audio parameters */ aghfp->audio_sink = cfm->audio_sink; aghfp->rx_bandwidth = cfm->rx_bandwidth; aghfp->tx_bandwidth = cfm->tx_bandwidth; aghfp->link_type = cfm->link_type; aghfp->audio_connection_state = aghfp_audio_connected; /* Tell the app about this */ if ( aghfpCallManagerActiveNotComplete(aghfp) ) { /* Audio connection request will have come from call manager */ aghfpManageCall(aghfp, CallEventAudioConnected, CallFlagSuccess); } else { /* Audio connection request will have come fom app */ sendAudioConnectCfmToApp(aghfp, aghfp_audio_connect_success, cfm->status); } } else { /* Give up if we are either attempting to accept in incoming connection or error code indicates it is pointless to continue. */ if ( cfm->status<=hci_error_host_timeout || (cfm->status>=hci_error_oetc_user && cfm->status<=hci_error_unknown_lmp_pdu) || aghfp->audio_connection_state==aghfp_audio_accepting ) { aghfp->audio_connection_state = aghfp_audio_disconnected; resetAudioParams(aghfp); /* SCO/eSCO connect failed */ if ( aghfpCallManagerActiveNotComplete(aghfp) ) { /* Audio connection request will have come from call manager */ aghfpManageCall(aghfp, CallEventAudioConnected, CallFlagFail); } else { /* Audio connection request will have come fom app */ sendAudioConnectCfmToApp(aghfp, aghfp_audio_connect_failure, cfm->status); } } else { /* This step failed, move onto next stage of connection attempt */ continueAudioConnectRequest(aghfp); } } } else { /* Should never get here */ AGHFP_DEBUG(("aghfpHandleSyncConnectCfm invalid state %d",aghfp->audio_connection_state)); } }
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; } }
/* Handle Codec Negotiation resopnse from the HF (AT+BCS) */ void aghfpHandleWbsCodecNegReq(AGHFP *aghfp, uint16 codecUUID16) { sync_pkt_type audio_packet_type = aghfp->audio_packet_type; aghfp_audio_params audio_params = aghfp->audio_params; uint16 codec; /* Codec bitmap used internally */ AGHFP_DEBUG(("aghfpHandleWbsCodecNegReq : ")); /* Translate from codec UUID16 format to internal bitmap. */ codec = WbsUuid16ToCodec((codecs_info*)&(aghfp->codecs_info), codecUUID16); /* Note that one bit should be set in the bitmaps and it must be the same bit for success. */ if(aghfp->use_wbs && (aghfp->use_codec == codec)) { AGHFP_DEBUG(("Starting WB-Speech eSCO\n")); /* Send OK */ aghfpSendOk(aghfp); /* audio_packet_type and audio_params already set to WBS values. */ /* Force connection create. WBS SCO connection are always initiated by the AG. */ if(aghfp->wbs_negotiate_action != aghfp_negotiate_no_audio) { aghfp->wbs_negotiate_action = aghfp_negotiate_audio_at_ag; } } else { AGHFP_DEBUG(("Falling back to request eSCO type\n")); /* send Error */ aghfpSendError(aghfp); /* Reset any saved codecs; Codec Negotiation aborted. */ aghfp->use_codec = 0; /* For normal SCO we only set up the SCO here if the AG initiated the connection. */ if (aghfp->wbs_negotiate_action == aghfp_negotiate_audio_at_ag) { /* Start eSCO Connection */ audio_packet_type = aghfp->audio_packet_type; audio_params = aghfp->audio_params; audio_params.override_wbs = TRUE; } } if (aghfp->wbs_negotiate_action == aghfp_negotiate_audio_at_ag) { /* Start eSCO Connection. We get here if we are setting up a WBS link or an AG initiated normal SCO. */ if (!aghfpCallManagerActiveNotComplete(aghfp)) { MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_AUDIO_CONNECT_REQ); AGHFP_DEBUG((" Normal Audio Connection\n")); message->audio_params = audio_params; message->packet_type = audio_packet_type; MessageSend(&aghfp->task, AGHFP_INTERNAL_AUDIO_CONNECT_REQ, message); } else { /* Save the audio packet type for Call Manager */ aghfpStoreAudioParams(aghfp, audio_packet_type, &audio_params); /* Answer the call again now that the WBS negotiation is complete. */ aghfpManageCall(aghfp, CallEventAnswer, CallFlagOpenAudio); } } aghfp->wbs_negotiate_action = aghfp_negotiate_undefined; /* Reset flag to ensure it is correct next time */ }