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

📄 a2dp_handler.c

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

FILE NAME
    a2dp_handler.c        

DESCRIPTION
    Deals with A2dp functionality.

*/


/****************************************************************************
    Header files
*/
#include "headset_private.h"
#include "a2dp_handler.h"
#include "av_stream_control.h"
#include "headset_common.h"
#include "headset_power.h"
#include "headset_tones.h"

#include <codec.h>
#include <kalimba.h>
#include <panic.h>
#include <ps.h>
#include <stdlib.h>


#ifdef DEBUG_A2DP
#define A2DP_DEBUG(x) DEBUG(x)
#else
#define A2DP_DEBUG(x) 
#endif


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

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


/**************************************************************************/
void avHeadsetRegisterSep(const headsetTaskData *app, a2dp_sep_type sep)
{
	a2dp_sep_config config;    
	config.sep_type = sep;
	config.params = 0;
	
    A2dpAddSep(app->a2dp, &config);
}


/**************************************************************************/
void avHeadsetHandleA2dpAddSepCfm(headsetTaskData* app, const A2DP_ADD_SEP_CFM_T* cfm)
{
    if(cfm->status == a2dp_success)
    {
		/* SBC is registered last, so wait for it.*/
        if (cfm->sep_type == a2dp_sbc)
        {
            avrcp_init_params config;
            config.device_type = avrcp_controller;
            config.priority = 50;

			/* Go ahead and Initialise the AVRCP library */
			AvrcpInit(&app->task, &config);
                    
			/* Change to Ready state */
			setA2dpState(app, avHeadsetA2dpReady);
		}
    }
    else
    {
        A2DP_DEBUG(("A2DP: Unable to register SEPs\n"));
	Panic();
    }
}


/**************************************************************************/
void avHeadsetHandleA2dpOpenInd(headsetTaskData* app, const A2DP_OPEN_IND_T* ind)
{   
    bdaddr bdaddr_ind;
    
    (void) SinkGetBdAddr(ind->media_sink, &bdaddr_ind);
 
    /* We are now connected */
    setA2dpState(app, avHeadsetA2dpConnected);
    
    /* Play connect tone */
    if (!MessageCancelAll(getAppTask(), APP_A2DP_CLOSE_TIMER))
        playConnectTone(app);
        
    /* Store the address of the device that just connecetd to us */
    (void)PsStore(LAST_USED_AV_SOURCE, &bdaddr_ind, sizeof(bdaddr)); 
    (void)PsStore(LAST_USED_AV_SOURCE_SEP, &(ind->sep_type), sizeof(a2dp_sep_type));
    
    /* Establish an AVRCP connection if required */
	if (app->avrcp_state == avHeadsetAvrcpReady)
	{
		/* Change to connecting state */
		setAvrcpState(app, avHeadsetAvrcpConnecting);
    
        /* Establish AVRCP connection */
		AvrcpConnect(app->avrcp, &bdaddr_ind);
	}

    /* Store the media sink */
    app->media_sink = ind->media_sink;
}


/**************************************************************************/
void avHeadsetHandleA2dpOpenCfm(headsetTaskData* app, const A2DP_OPEN_CFM_T* cfm)
{
    bdaddr bdaddr_cfm;
    
    if (cfm->result == a2dp_success)
    {
		(void)PsStore(LAST_USED_AV_SOURCE_SEP, &(cfm->sep_type), sizeof(a2dp_sep_type));  
        A2dpStart(app->a2dp, cfm->media_sink); 
        
        setA2dpState(app, avHeadsetA2dpConnected);
        
        /* Play connect tone */
        if (!MessageCancelAll(getAppTask(), APP_A2DP_CLOSE_TIMER))
            playConnectTone(app);
        
        /* Store the media sink and source id*/
        app->media_sink = cfm->media_sink;
        
        /* Establish an AVRCP connection if required */
	    if (app->avrcp_state == avHeadsetAvrcpReady)
        {
            if (SinkGetBdAddr(cfm->media_sink, &bdaddr_cfm))
            {
                setAvrcpState(app, avHeadsetAvrcpConnecting);
		        AvrcpConnect(app->avrcp, &bdaddr_cfm);
            }
	    }
    }
    else
    {
		playErrorTone(app);
        setA2dpState(app, avHeadsetA2dpReady);
    }
    app->headset_connecting_av = 0;
}


/**************************************************************************/
void avHeadsetHandleA2dpStartInd(headsetTaskData* app, const A2DP_START_IND_T* ind)
{
    if (!app->media_sink || (app->a2dp_state == avHeadsetA2dpStreaming))
        return;
    
    if (app->sco_sink)
        /* SCO is active so don't start AV */
        A2dpSuspend(app->a2dp, ind->media_sink);
    else
        avHeadsetAvStreamStart(app);
    
    /* Change to streaming state */
    setA2dpState(app, avHeadsetA2dpStreaming);
    
    /* Cancel pairing mode */
    (void) MessageCancelAll(getAppTask(), APP_PAIR_MODE_END_IND);
    MessageSend(getAppTask(), APP_PAIR_MODE_END_IND, 0);
}


/**************************************************************************/
void avHeadsetHandleA2dpStartCfm(headsetTaskData* app, const A2DP_START_CFM_T* cfm)
{
    if (cfm->result == a2dp_success)
    {   
        /* Cancel pairing mode */
        (void) MessageCancelAll(getAppTask(), APP_PAIR_MODE_END_IND);
        MessageSend(getAppTask(), APP_PAIR_MODE_END_IND, 0);

        /* start Kalimba decoding if it isn't already */
        if (app->av_stream_stopped)
        {			
            if (app->sco_sink)
            {
                /* 
                    SCO has become active while we were waiting for a START_CFM.
				    AV doesn't want to be streaming now, so we must try to 
				    suspend the source again.
				*/
                A2dpSuspend(app->a2dp, cfm->media_sink);
                return;
            }
            else
            {
                avHeadsetAvStreamStart(app);
            }
        } 
        
        setA2dpState(app, avHeadsetA2dpStreaming);
    }
    else
    {
        /* failed to start, close the connection */
        A2dpClose(app->a2dp, cfm->media_sink);

        if (app->avrcp_state == avHeadsetAvrcpConnected)
            AvrcpDisconnect(app->avrcp);
    }
}


/**************************************************************************/
void avHeadsetHandleA2dpSuspendInd(headsetTaskData *app)
{
    /* Change to connected state */
    setA2dpState(app, avHeadsetA2dpConnected);
    avHeadsetAvStreamStop(app, FALSE);
}


/**************************************************************************/
void avHeadsetHandleA2dpSuspendCfm(headsetTaskData* app, const A2DP_SUSPEND_CFM_T* ind)
{
    if (ind->result == a2dp_success)
    {
        setA2dpState(app, avHeadsetA2dpConnected);
        
        if (!app->av_stream_stopped)
        {
            /* We must have had a stream restart at this end occuring so restart AV source */
            A2dpStart(app->a2dp, app->media_sink);
        }
        else
        {
            /* We have suspended the AV source. */
            app->sent_suspend = TRUE;
        }
    }
}


/**************************************************************************/
void avHeadsetHandleA2dpCloseInd(headsetTaskData *app, const A2DP_CLOSE_IND_T *ind)
{
    /* Stop the media stream */
    avHeadsetAvStreamStop(app,FALSE);

    /* Power down the codec */
    CodecPowerDown(app->codec_task);

    /* Change to ready state */
    setA2dpState(app, avHeadsetA2dpReady);
    
    if (app->pcm_audio_state == pcm_tone_to_av)
        setPcmState(app, pcm_tone);
    if (app->pcm_audio_state == pcm_av)
        setPcmState(app, pcm_none);

    /* Switch to hfp mode */
    app->active_profile = hfp_active;
    
    if (app->avrcp_state == avHeadsetAvrcpConnected)
        AvrcpDisconnect(app->avrcp);
    
    app->media_sink = 0;

    /* Reconnect on link loss */
    if (ind->result == a2dp_disconnect_link_loss)
        avHeadsetHandleAvConnectRequest(app);

    /* If we're ready to power down don't wait any longer */    
    headsetCheckPowerDownStatus(app);
    
    MessageSendLater(getAppTask(), APP_A2DP_CLOSE_TIMER, 0, 1000);
}


/**************************************************************************/
void avHeadsetHandleA2dpCloseCfm(headsetTaskData* app)
{
    /* Stop the media stream */
    avHeadsetAvStreamStop(app,FALSE);
    /* Switch to hfp mode */
    app->active_profile = hfp_active;

    /* Change to ready state */
    setA2dpState(app, avHeadsetA2dpReady);
    
    app->media_sink = 0;

    /* If we're ready to power down don't wait any longer */    
    headsetCheckPowerDownStatus(app);
    
    MessageSendLater(getAppTask(), APP_A2DP_CLOSE_TIMER, 0, 1000);
}


/**************************************************************************/
void avHeadsetHandleA2dpCodecSettingsInd(headsetTaskData *theAvApp, const A2DP_CODEC_SETTINGS_IND_T *ind)
{
	/* Store the codec config settings */
	theAvApp->channel_mode = ind->channel_mode;
	theAvApp->rate = ind->rate;
}

/****************************************************************************/
void avHeadsetHandleAvConnectRequest(headsetTaskData *app)
{
    bdaddr addr;
	uint8 mp3_enabled = 0;
	a2dp_sep_type sep_type = a2dp_sbc;
    /* Retrieve the address of the last used AG from PS */
    if (!PsRetrieve(LAST_USED_AV_SOURCE, &addr, sizeof(bdaddr)))
    {
		if (!PsRetrieve(LAST_PAIRED_DEVICE, &addr, sizeof(bdaddr)))
		{
            /* Play an error tone to indicate we don't have a valid address */
		    playErrorTone(app);		    
		    return;
	    }
	}
			
    if (app->a2dp_state == avHeadsetA2dpReady)
    {
        app->headset_connecting_av = 1;
        setA2dpState(app, avHeadsetA2dpInitiating);
		/*If last connected using MP3 and if MP3 is enabled, reconnect using MP3, otherwise 
		  using SBC*/

		if (PsRetrieve(MP3_ENABLED, &mp3_enabled, sizeof(uint8)))
			if (mp3_enabled)
			{
				if (!PsRetrieve(LAST_USED_AV_SOURCE_SEP, &sep_type, sizeof(a2dp_sep_type)))
					sep_type = a2dp_sbc;
			}

        A2dpOpen(app->a2dp, sep_type, &addr);
    }
}

⌨️ 快捷键说明

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