/**************************************************************************** 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); } }
/* 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); } }
/* Attempt to create a new audio (Synchronous) connection */ static void audioConnectRequest(AGHFP *aghfp, sync_pkt_type packet_type, const aghfp_audio_params *audio_params) { if ( !aghfpCallManagerActiveNotComplete(aghfp) ) { if ( aghfpStoreAudioParams(aghfp, packet_type, audio_params) ) { startAudioConnectRequest(aghfp); } else { /* Inform app that one or more parameters were invalid */ sendAudioConnectCfmToApp(aghfp, aghfp_audio_connect_invalid_params, hci_success); } } else { /* Inform app that call manager is active, setting up or shutting down a call */ sendAudioConnectCfmToApp(aghfp, aghfp_audio_connect_call_manager_active, hci_success); } }
/* Handle set audio parameters request from the app. */ void aghfpHandleSetAudioParamsReq(AGHFP *aghfp, const AGHFP_INTERNAL_SET_AUDIO_PARAMS_REQ_T *req) { /* Only act upon the apps request if in the correct state. */ switch ( aghfp->audio_connection_state ) { case aghfp_audio_disconnected: case aghfp_audio_codec_connect: aghfpStoreAudioParams(aghfp, req->packet_type, &req->audio_params); /* Continue the Codec Connection */ aghfpHandleWbsCodecConReqProcessing(aghfp); break; case aghfp_audio_connecting_esco: case aghfp_audio_connecting_sco: case aghfp_audio_accepting: case aghfp_audio_disconnecting: case aghfp_audio_connected: default: AGHFP_DEBUG(("aghfpHandleAudioConnectReq invalid state %d\n",aghfp->audio_connection_state)); 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 */ }