⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hfp_slc.c

📁 针对bluelab3.42的handsfree车载蓝牙的参考
💻 C
字号:
    /****************************************************************************
Copyright (C) Cambridge Silicon Radio Ltd. 2004-2006
Part of BlueLab 3.4.2-release

FILE NAME
    hfp_slc.c

DESCRIPTION
    Handles the HFP Connection.

*/


/****************************************************************************
    Header files
*/
#include "headset_private.h"
#include "av_stream_control.h"
#include "hfp_audio.h"
#include "headset_common.h"
#include "headset_power.h"
#include "hfp_ring.h"
#include "hfp_slc.h"
#include "headset_tones.h"

#include <connection.h>
#include <hfp.h>
#include <panic.h>
#include <ps.h>


static void playConnectTone(headsetTaskData* app)
{
    headsetPlayTone(app, tone_type_connect);
}

static void playErrorTone(headsetTaskData* app)
{
    headsetPlayTone(app, tone_type_error);
}

static void slcConnectFail(headsetTaskData *app, bool play_tone)
{
    /* Update the app state */
    setHfpState(app, headsetReady);

    /* No connection */
    app->profile_connected = hfp_no_profile;

    /* Cancel the queued button presses */
    (void) MessageCancelAll(&app->task, BUTTON_MFB_SHORT);    
    (void) MessageCancelAll(&app->task, BUTTON_MFB_LONG_RELEASE);

    if (app->headset_connecting_hfp > 1)
    {
        MessageSend(getAppTask(), APP_HFP_SLC_REQ, 0);
    }
    else
    {
        (void) MessageCancelAll(getAppTask(), APP_HFP_SLC_TIMEOUT_IND);
        app->headset_connecting_hfp = 0;

        /* Play an error tone to indicate the connect attempt failed. */
        if (play_tone)
            playErrorTone(app);

        /* Restart music if streaming */
        if (app->av_stream_stopped)
            MessageSend(getAppTask(), APP_MUSIC_RESTART_IND, 0);
    }
}


/****************************************************************************
NAME    

    hfpHeadsetHandleSlcConnectInd
    
DESCRIPTION
    Handle a request to establish an SLC from the AG.

RETURNS
    void
*/
void hfpHeadsetHandleSlcConnectInd(headsetTaskData *app, const HFP_SLC_CONNECT_IND_T *ind)
{
    /* We support more than one HFP so check which one this request is for */   
    if (app->profile_connected == hfp_no_profile)
    {
        HfpSlcConnectResponse(ind->hfp, 1, &ind->addr, 0);
        
        /* Update the app state */
        setHfpState(app, headsetConnecting);

        /* See whether we are connecting as HSP or HFP */
        if (ind->hfp == app->hfp)
            app->profile_connected = hfp_handsfree_profile;
        else if (ind->hfp == app->hsp)
            app->profile_connected = hfp_headset_profile;
        else
            /* Something is wrong we should be either hfp or hsp */
            Panic();
    }
    else
    {
        /* Reject the connect attempt we're already connected */
        HfpSlcConnectResponse(ind->hfp, 0, &ind->addr, 0);
    }
}


/****************************************************************************
NAME    
    hfpHeadsetHandleSlcConnectCfm
    
DESCRIPTION
    Confirmation that the SLC has been established (or not).

RETURNS
    void
*/
void hfpHeadsetHandleSlcConnectCfm(headsetTaskData *app, const HFP_SLC_CONNECT_CFM_T *cfm)
{
    /* Check the status of the SLC attempt */
    if (cfm->status == hfp_connect_success)
    {
		bdaddr ag_addr;

        /* Update the app state */
        if (app->hfp_state == headsetConnecting)
            setHfpState(app, headsetConnected);
        
        /* Play connect tone */
        playConnectTone(app);
		
		/*End pairing mode*/
        MessageSend(getAppTask(), APP_PAIR_MODE_END_IND, 0);
        
		(void) MessageCancelAll(getAppTask(), APP_HFP_SLC_TIMEOUT_IND);
		app->headset_connecting_hfp = 0;

		/* Read the remote supported features of the AG */
		ConnectionReadRemoteSuppFeatures(getAppTask(), cfm->sink);

		/* Store the address as the last used AG which can be obtained from the sink */
		if (SinkGetBdAddr(cfm->sink, &ag_addr))
			(void) PsStore(LAST_USED_AG, &ag_addr, sizeof(bdaddr)); 
        
        /* If there is a pending APP_MUSIC_RESTART_IND message then it must have
           been sent because there was HFP link-loss and the AV stream was suspended 
           while the headset tried to reconnect back to the AG, to stop any AV stuttering.
           As the HFP connect has been a success, the AV can be restarted now.
        */
        if (MessageCancelAll(getAppTask(), APP_MUSIC_RESTART_IND))
            MessageSend(getAppTask(), APP_MUSIC_RESTART_IND, 0);    
        
        /* Inform AG of the current gain settings */
        if (app->profile_connected == hfp_handsfree_profile)
        {
            HfpSendSpeakerVolume(app->hfp, (uint16)app->speaker_volume.hfp_volume);
            HfpSendMicrophoneVolume(app->hfp , app->mic_volume);
        }
    }
    else if (cfm->status == hfp_connect_sdp_fail)
    {
        /* We failed to find the requested profile */
        if (cfm->hfp == app->hfp)
        {
            /* Didn't find HFP so try HSP */
            hfpHeadsetHandleSlcConnectRequest(app, hfp_headset_profile);
        }
        else if (cfm->hfp == app->hsp)
        {
            /* We try the HSP after we've tried HFP so this AG supports neither, give up */
            slcConnectFail(app, 1);
        }
        else
            /* Unknown profile instance */
            Panic();
    }
    else if (cfm->status == hfp_connect_failed)
    {
        /* Something failed during SLC establishment, check we're not trying to disconnect */
        if (app->headset_power_state == power_state_powering_down)
        {
            slcConnectFail(app, 0);
            headsetCheckPowerDownStatus(app);
        }
        else
            slcConnectFail(app, 1);
    }
    else
    {
        /* Update local state to reflect this */
        slcConnectFail(app, 1);
    }
}


/*******************Ps*********************************************************
NAME    
    hfpHeadsetHandleSlcConnectRequest
    
DESCRIPTION
    Request to create a connection to a remote AG.

RETURNS
    void
*/
void hfpHeadsetHandleSlcConnectRequest(headsetTaskData *app, hfp_profile profile)
{
    bdaddr addr;    

    /* Retrieve the address of the last used AG from PS */
    if (!PsRetrieve(LAST_USED_AG, &addr, sizeof(bdaddr)))
    {
		if (!PsRetrieve(LAST_PAIRED_DEVICE, &addr, sizeof(bdaddr)))
		{
			slcConnectFail(app, 1);
			return;
		}
        /* Play an error tone to indicate we don't have a valid address */
        playErrorTone(app);
    }
    
    /* Update the app state */
    setHfpState(app, headsetConnecting);

    if (profile == hfp_handsfree_profile)
    {
        app->profile_connected = hfp_handsfree_profile;

        /* Issue a connect request for HFP */
        HfpSlcConnect(app->hfp, &addr, 0);
    }
    else if (profile == hfp_headset_profile)
    {
        app->profile_connected = hfp_headset_profile;

        /* Issue a connect request for HFP */
        HfpSlcConnect(app->hsp, &addr, 0);
    }
    else
        /* The app should know what profile it wants to connect as */
        Panic();
}


/****************************************************************************
NAME    
    hfpHeadsetDisconnectSlc
    
DESCRIPTION
    Disconnect the SLC associated with this profile instance.

RETURNS
    void
*/
void hfpHeadsetDisconnectSlc(const headsetTaskData *app)
{
    /* Issue the disconnect request and let the HFP lib do the rest */
    HfpSlcDisconnect(app->hfp);
}


/****************************************************************************
NAME    
    hfpHeadsetHandleSlcDisconnectInd
    
DESCRIPTION
    Indication that the SLC has been released.

RETURNS
    void
*/
void hfpHeadsetHandleSlcDisconnectInd(headsetTaskData *app, const HFP_SLC_DISCONNECT_IND_T *ind)
{
	/*	
        Handle the case where an incoming call is rejected using the headset profile.
		As we get no indicator info, the AV must be restarted on a SLC disconnect.
	*/
    if ((app->profile_connected == hfp_headset_profile) && app->av_stream_stopped)
    {
        headsetRestartAV(app);
    }

    /* Update the app state */
    setHfpState(app, headsetReady);
    
    /* Connection disconnected */
    app->profile_connected = hfp_no_profile;
    app->voice.voice_recognition_enabled = 0;
    app->voice.old_voice_recognition_enabled = 0;
    
    /* Cancel a voice request that could be in progress after connection */
    (void) MessageCancelAll(getAppTask(), BUTTON_MFB_SHORT);

    /* Store the latest volume setting */
    (void) PsStore(VOLUME_LEVEL, &app->speaker_volume, sizeof(app->speaker_volume));
    
    /* Procedure for abnormal link-loss */
    if (ind->status == hfp_disconnect_link_loss)
    {
        /* If AV is streaming then Suspend it as the HFP reconnect will 
           cause interruptions in the audio.
        */
        (void) MessageCancelAll(getAppTask(), APP_MUSIC_RESTART_IND);
        MessageSendLater(getAppTask(), APP_MUSIC_RESTART_IND, 0, SLC_CONNECT_TIMEOUT + 1000);
        if (app->a2dp_state == avHeadsetA2dpStreaming)
        {
            avHeadsetAvStreamStop(app, TRUE);    
        }

		/* Send a reconnect attempt */
        app->headset_connecting_hfp = 2;
        MessageSend(getAppTask(), APP_HFP_SLC_REQ, 0);
        
        /* Set the connect attempt timeout. */
        MessageSendLater(getAppTask(), APP_HFP_SLC_TIMEOUT_IND, 0, (uint32) SLC_CONNECT_TIMEOUT);
    }
    
    /* If we're ready to power down don't wait any longer */
    headsetCheckPowerDownStatus(app);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -