/****************************************************************************
NAME    
    sinkHangUpCall
    
DESCRIPTION
    Hang up the call from the device.

RETURNS
    void
*/
void sinkHangUpCall( void )
{
    /* Determine which is the current active call */  
    hfp_link_priority priority = hfp_invalid_link;
    hfp_call_state call_state;
    
    /* Get profile if AG with audio, also ensure AG is actually in a call, otherwise try other methods */
    if((theSink.routed_audio)&&(HfpLinkGetCallState(HfpLinkPriorityFromAudioSink(theSink.routed_audio), &call_state)&& (call_state)))    
        priority = HfpLinkPriorityFromAudioSink(theSink.routed_audio);
    
    /* No audio so use AG state */
    if(!priority)
        priority = HfpLinkPriorityFromCallState(hfp_call_state_active);

    /* No active call, check for an outgoing call to terminate */
    if(!priority)
        priority = HfpLinkPriorityFromCallState(hfp_call_state_outgoing);

    /* No active/outgoing calls, check for TWC state */
    if(!priority)
        priority = HfpLinkPriorityWithActiveCall(FALSE);

    /* no active calls but still a held call on the phone */
    if(!priority)
        priority = HfpLinkPriorityFromCallState(hfp_call_state_held_remaining); 
    
    /* If match found */
    if(priority && HfpLinkGetCallState(priority, &call_state))
    {
        switch(call_state)
        {
            case hfp_call_state_twc_incoming:
            case hfp_call_state_twc_outgoing:
            case hfp_call_state_held_active:
            case hfp_call_state_multiparty:
                CM_DEBUG(("CM: HangUp TWC active Call on AG%x\n",priority)) ;
                HfpCallHoldActionRequest(priority, hfp_chld_release_active_accept_other, 0);

            break;
            case hfp_call_state_held_remaining:
                CM_DEBUG(("CM: HangUp TWC held Call on AG%x\n",priority)) ;
                HfpCallHoldActionRequest(priority, hfp_chld_release_held_reject_waiting, 0);
            break;
            default:
                /* Terminate call using AT+CHUP */
                CM_DEBUG(("CM: HangUp Call on AG%x\n",priority)) ;
                HfpCallTerminateRequest(priority);
            break;
        }
    }
}
Exemple #2
0
/****************************************************************************
NAME    
    sinkCheckForAudioTransfer
    
DESCRIPTION
    checks on connection for an audio connction and performs a transfer if not present

RETURNS
    void
*/
void sinkCheckForAudioTransfer ( void )
{
    sinkState lState = stateManagerGetState() ;
    
    AUD_DEBUG(("AUD: Tx[%d] [%x]\n", lState , (int)theSink.routed_audio)) ;
    
    switch (lState)
    {
        case deviceIncomingCallEstablish :
        case deviceThreeWayCallWaiting :
        case deviceThreeWayCallOnHold :
        case deviceThreeWayMulticall :
        case deviceIncomingCallOnHold : 
        case deviceActiveCallNoSCO :
        {              
            Sink sink;            
            hfp_call_state state;  
            hfp_link_priority priority = hfp_invalid_link;
              
            /* check call state and sink of AG1 */
            if((HfpLinkGetCallState(hfp_primary_link, &state))&&(state == hfp_call_state_active)&&
               (HfpLinkGetAudioSink(hfp_primary_link, &sink))&&(!sink))
            {
                priority = hfp_primary_link;
            }
            /* or check call state and sink of AG2 */
            else if((HfpLinkGetCallState(hfp_secondary_link, &state))&&(state == hfp_call_state_active)&&
                    (HfpLinkGetAudioSink(hfp_secondary_link, &sink))&&(!sink))    
            {
                priority = hfp_secondary_link;
            }
            /* if call found with no audio */
            if (priority)
            {
                hfp_audio_params * audio_params = NULL;
                HfpAudioTransferRequest(priority, 
                                        hfp_audio_to_hfp , 
                                        theSink.HFP_supp_features.packet_types,
                                        audio_params );
            }    
        }
        break ;
        default:
        break;
    }
}
/****************************************************************************
NAME    
    sinkRejectHeldIncomingCall
    
DESCRIPTION
	looks for a held incoming call and performs the twc reject held incoming
    call function

RETURNS
    void
*/
void sinkRejectHeldIncomingCall(void)
 {
     hfp_call_state CallState;
     /* find incoming held call */
     if((HfpLinkGetCallState(hfp_primary_link, &CallState))&&
        (CallState == hfp_call_state_incoming_held))
     {
         CM_DEBUG(("MAIN: Hold incoming Call on AG1\n")) ;
         HfpResponseHoldActionRequest(hfp_primary_link, hfp_reject_held_incoming_call);
     }
     else if((HfpLinkGetCallState(hfp_secondary_link, &CallState))&&
             (CallState == hfp_call_state_incoming_held))
     {
         CM_DEBUG(("MAIN: Hold incoming Call on AG2\n")) ;
         HfpResponseHoldActionRequest(hfp_secondary_link, hfp_reject_held_incoming_call);                
     }
 }
/****************************************************************************
NAME    
    sinkPlaceIncomingCallOnHold
    
DESCRIPTION
	looks for an incoming call and performs the twc hold incoming call function

RETURNS
    void
*/
void sinkPlaceIncomingCallOnHold(void)
{
     hfp_call_state CallState;
     /* find incoming call to hold */
     if((HfpLinkGetCallState(hfp_primary_link, &CallState))&&
        (CallState == hfp_call_state_incoming))
     {
         CM_DEBUG(("MAIN: Hold incoming Call on AG1\n")) ;
         HfpResponseHoldActionRequest(hfp_primary_link, hfp_hold_incoming_call);
     }
     else if((HfpLinkGetCallState(hfp_secondary_link, &CallState))&&
             (CallState == hfp_call_state_incoming))
     {
         CM_DEBUG(("MAIN: Hold incoming Call on AG2\n")) ;
         HfpResponseHoldActionRequest(hfp_secondary_link, hfp_hold_incoming_call);                
     }
 }
Exemple #5
0
/****************************************************************************
NAME    
    audioHandleSyncConnectCfm
    
DESCRIPTION
    Handle HFP_AUDIO_CONNECT_CFM.  This indicates that an incoming sychronous 
    connection has been established

RETURNS
    
*/
void audioHandleSyncConnectCfm ( const HFP_AUDIO_CONNECT_CFM_T * pCfm )
{       
    uint8 index = PROFILE_INDEX(pCfm->priority);
    hfp_call_state CallState;
    
    /* Get the priority of the other link */
    hfp_link_priority other = (pCfm->priority == hfp_primary_link) ? hfp_secondary_link : hfp_primary_link;
    
    
    AUD_DEBUG(("Synchronous Connect Cfm from [%x]:\n", (uint16)pCfm->priority)) ;
 
    /* if successful */
    if ( pCfm->status == hfp_success)
    {      
        Sink sink;
        
        /* obtain sink for this audio connection */
        if(HfpLinkGetSlcSink(pCfm->priority, &sink))
        {
            /* Send our link policy settings for active SCO role */
            linkPolicyUseHfpSettings(pCfm->priority, sink);
        }

        /* store in individual hfp struct as it may be necessary to disconnect and reconnect
           audio on a per hfp basis for multipoint multiparty calling */
        theSink.profile_data[index].audio.tx_bandwidth= pCfm->tx_bandwidth;
        theSink.profile_data[index].audio.link_type= pCfm->link_type;           
        theSink.profile_data[index].audio.codec_selected = pCfm->codec;           
                
        /* Send an event to indicate that a SCO has been opened */           
        /* this indicates that an audio connection has been successfully created to the AG*/
        MessageSend ( &theSink.task , EventSCOLinkOpen , 0 ) ;

        /* update the audio priority state 
           is this sco a streaming audio sco?, check call state for this ag */
        if(HfpLinkGetCallState(pCfm->priority, &CallState))
        {          
            /* determine sco priority based on call status */
            switch(CallState)
            {
                /* no call so this is a steaming audio connection */
                case hfp_call_state_idle:
                    setScoPriorityFromHfpPriority(pCfm->priority, sco_streaming_audio);
                break;
                
                /* incoming call so this is an inband ring sco */
                case hfp_call_state_incoming:
                case hfp_call_state_incoming_held:
                case hfp_call_state_twc_incoming:
                    setScoPriorityFromHfpPriority(pCfm->priority, sco_inband_ring);                    
                break;
   
                /* active call states so this sco has highest priority */
                case hfp_call_state_active:
                case hfp_call_state_twc_outgoing:
                    /* this audio connection may have been the result of the an audio transfer
                       from the AG and there is already an active call on the other AG, check for this
                       and make this new audio connection held leaving the other routed audio connection 
                       intact */
                    if(getScoPriorityFromHfpPriority(other)==sco_active_call)                    
                        setScoPriorityFromHfpPriority(pCfm->priority, sco_held_call);                    
                    else
                        setScoPriorityFromHfpPriority(pCfm->priority, sco_active_call);                    
                break;
                
                /* an outgoing call sco has highest priority, if there is a call on other AG
                   it needs to be put on hold whilst this outgoing call is made */
                case hfp_call_state_outgoing:
                    /* does other AG have active call on it?, if so hold the audio */
                    if(getScoPriorityFromHfpPriority(other)==sco_active_call)
                        setScoPriorityFromHfpPriority(other, sco_held_call);
                    /* make the outgoing call audio the one that gets routed */
                    setScoPriorityFromHfpPriority(pCfm->priority, sco_active_call);
                break;

                /* this call is held so the sco is put to on hold priority which is lower than
                   active call but higher than streaming */
                case hfp_call_state_held_active:
                case hfp_call_state_held_remaining:
                    if(theSink.routed_audio)                    
                        setScoPriorityFromHfpPriority(pCfm->priority, sco_held_call);                    
                break;
   
                /* non covered states treat as highest priority sco connection */
                default:
                    setScoPriorityFromHfpPriority(pCfm->priority, sco_active_call);                    
                break;
            }
        }
        
        /* route the appropriate audio connection */
        audioHandleRouting(audio_source_none);

        /*change the active call state if necessary*/
        if ((stateManagerGetState() == deviceActiveCallNoSCO) )
        {
            stateManagerEnterActiveCallState();
        }
                       
#ifdef DEBUG_AUDIO
        switch (pCfm->link_type)
        {
            case (sync_link_unknown):
                AUD_DEBUG(("AUD: Link = ?\n")) ;
            break ;
            case (sync_link_sco) :
                AUD_DEBUG(("AUD: Link = SCO\n")) ;
            break;
            case sync_link_esco:
                AUD_DEBUG(("AUD: Link = eSCO\n")) ;
            break ;    
        }
#endif        

    }
    else
    {
        AUD_DEBUG(("Synchronous Connect Cfm: FAILED\n")) ;       
    }
    AUD_DEBUG(("AUD : Sco->\n")) ;
}