Esempio n. 1
0
/****************************************************************************
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;
        }
    }
}
Esempio n. 2
0
/****************************************************************************
NAME    
    sinkAnswerOrRejectCall
    
DESCRIPTION
    Answer an incoming call from the device

RETURNS
    void
*/
void sinkAnswerOrRejectCall( bool Action )
{
    hfp_link_priority priority;
    
    /* if the SR plugin is running, disconnect it */
    MessageSend ( &theSink.task , EventSysSpeechRecognitionStop , 0 ) ;

    /* get profile if AG with incoming call */
    priority = HfpLinkPriorityFromCallState(hfp_call_state_incoming);

    CM_DEBUG(("CM: Answer Call on AG%x\n",priority)) ;

    /* if match found */
    if(priority)
    {
        /* answer call */
        HfpCallAnswerRequest(priority, Action);
        theSink.profile_data[PROFILE_INDEX(priority)].status.local_call_action = TRUE; 
    }
    /*terminate the ring tone*/
    ToneTerminate();
}
Esempio n. 3
0
/****************************************************************************
NAME    
    sinkHandleSlcConnectCfm
    
DESCRIPTION
    Confirmation that the SLC has been established (or not).

RETURNS
    void
*/
bool sinkHandleSlcConnectCfm( const HFP_SLC_CONNECT_CFM_T *cfm )
{
    sink_attributes attributes;
    bool lResult = FALSE;
    
#ifdef ENABLE_PEER    
    inquiry_result_t* connecting_device = inquiryGetConnectingDevice();
#endif
    
    deviceManagerGetDefaultAttributes(&attributes, FALSE);
    (void)deviceManagerGetAttributes(&attributes, &cfm->bd_addr);
    
    /* cancel any link loss reminders */        
    MessageCancelAll(&theSink.task , EventSysLinkLoss );

    /* Check the status of the SLC attempt */
    if (cfm->status == hfp_connect_success)
    {
        SLC_DEBUG(("SLC: ConnCfm - Success\n")) ;
        lResult = TRUE ;

        /* update the profile volume level */
        theSink.profile_data[PROFILE_INDEX(cfm->priority)].audio.gSMVolumeLevel = attributes.hfp.volume;     
        /* Handle new connection setup */
        slcConnectionComplete(cfm->priority, cfm->sink, (bdaddr *)&cfm->bd_addr);
        /* Handle common setup for new SLC/link loss */
        slcConnectionSetup(cfm->priority, cfm->sink, (bdaddr *)&cfm->bd_addr);
        /* Record the position of the device in the PDL - prevents reconnection later */
        theSink.profile_data[PROFILE_INDEX(cfm->priority)].status.list_id = deviceManagerSetPriority((bdaddr *)&cfm->bd_addr);
        
#ifdef ENABLE_PEER
        /* If RSSI pairing, check inquiry results for A2DP support */
        if (theSink.inquiry.action == rssi_pairing)
        {
            if ((connecting_device != NULL) && BdaddrIsSame(&connecting_device->bd_addr, &cfm->bd_addr) && (connecting_device->remote_profiles & profile_a2dp))
            {
                attributes.profiles |= sink_a2dp;
            }
        }
#endif
        
        /* Make sure we store this device */
        attributes.profiles |= sink_hfp;
        deviceManagerStoreAttributes(&attributes, &cfm->bd_addr);
                
        /* if rssi pairing check to see if need to cancel rssi pairing or not */           
        if(theSink.inquiry.action == rssi_pairing)
        {   
            /* if rssi pairing has completed and the device being connected currently doesn't support A2DP, then stop it progressing further */            
            if(!((theSink.features.PairIfPDLLessThan) && ( ConnectionTrustedDeviceListSize() < theSink.features.PairIfPDLLessThan )))
            {
#ifdef ENABLE_PEER                
                if(!((connecting_device != NULL) && BdaddrIsSame(&connecting_device->bd_addr, &cfm->bd_addr) && (connecting_device->remote_profiles & profile_a2dp)))
#endif
                {
                    inquiryStop();
                }
            }
        }

        /* Disable A2dp link loss management if connected on remote device */
        if( theSink.a2dp_link_data && (theSink.a2dp_link_data->connected[a2dp_primary]) && BdaddrIsSame(&cfm->bd_addr, &theSink.a2dp_link_data->bd_addr[a2dp_primary]) )
        {
            A2dpDeviceManageLinkloss(theSink.a2dp_link_data->device_id[a2dp_primary], FALSE);
        }
        else if( theSink.a2dp_link_data && (theSink.a2dp_link_data->connected[a2dp_secondary]) && BdaddrIsSame(&cfm->bd_addr, &theSink.a2dp_link_data->bd_addr[a2dp_secondary]) )
        {
            A2dpDeviceManageLinkloss(theSink.a2dp_link_data->device_id[a2dp_secondary], FALSE);
        }

        /* Auto answer call if ringing - only answer the incoming call if its 
           on the connecting AG */
        if ( (theSink.features.AutoAnswerOnConnect) && (HfpLinkPriorityFromCallState(hfp_call_state_incoming) == cfm->priority) && (stateManagerGetState() < deviceActiveCallSCO) )
        {
            MessageSend (&theSink.task , EventUsrAnswer , 0 ) ;
            SLC_DEBUG(("SLC: AutoAnswer triggered\n")) ;
        }
    }
    else
    {
        SLC_DEBUG(("SLC: ConnCfm - Fail\n")) ;
        
        /* a connection timeout will arrive here, need to report fail for multipoint
           connections also such that a link loss retry will be performed */
        if(!stateManagerIsConnected() || theSink.MultipointEnable)
        {
            /* Update local state to reflect this */
            slcConnectFail();
        }
    }
 
    /* if using multipoint and both devices are connected disable connectable */
    if((theSink.MultipointEnable) && (deviceManagerNumConnectedDevs() == MAX_MULTIPOINT_CONNECTIONS))
    {
        SLC_DEBUG(("SLC: disable Conn \n" ));
        MessageCancelAll(&theSink.task, EventSysConnectableTimeout);

#ifdef ENABLE_SUBWOOFER     
        if(SwatGetSignallingSink(theSink.rundata->subwoofer.dev_id))
        {
           sinkDisableConnectable();            
        }        
#else
        sinkDisableConnectable();            
#endif        
    }
    
    SLC_DEBUG(("SLC: Connect A2DP? En=%d att=%d\n",theSink.features.EnableA2dpStreaming,attributes.profiles)) ;
    
    /* if the AG supports A2DP profile attempt to connect to it if auto reconnect is enabled */
    if ((theSink.features.EnableA2dpStreaming) && 
         ((!cfm->priority)||(cfm->status == hfp_connect_success) || (cfm->status == hfp_connect_sdp_fail) || (cfm->status == hfp_connect_rejected)) &&
         ((slcDetermineConnectAction() & AR_Rssi)||(attributes.profiles & sink_a2dp)) &&                         
         ((slcDetermineConnectAction() & AR_Rssi)||(stateManagerGetState()!=deviceConnDiscoverable)))                          
    {
        SLC_DEBUG(("SLC: Connecting A2DP Remote %x\n",gSlcData.gSlcConnectRemote)) ;
        /* attempt connection to device supporting A2DP */
        theSink.a2dp_link_data->remote_connection = gSlcData.gSlcConnectRemote;
        A2dpSignallingConnectRequest((bdaddr *)&cfm->bd_addr);
        MessageCancelFirst(&theSink.task, EventSysContinueSlcConnectRequest);
        /* if rssi pairing check to see if need to cancel rssi pairing or not */           
        if(theSink.inquiry.action == rssi_pairing)
        {
            /* if rssi pairing has completed then stop it progressing further */            
            if(!((theSink.features.PairIfPDLLessThan)&&( ConnectionTrustedDeviceListSize() < theSink.features.PairIfPDLLessThan )))
            {
#ifdef ENABLE_PEER                
                if(!((connecting_device != NULL) && BdaddrIsSame(&connecting_device->bd_addr, &cfm->bd_addr) && (connecting_device->remote_profiles & profile_a2dp)))
#endif                   
                {
                    inquiryStop();
                }
            }
        }
    }
    else
    {
        /* reset connection via remote ag instead of device flag */
        gSlcData.gSlcConnectRemote = FALSE;
    }

#ifdef ENABLE_MAPC
    mapcMasConnectRequest((bdaddr *)&cfm->bd_addr);    
#endif
    
    return lResult ;
}