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

📄 hfp_audio.c

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

FILE NAME
    hfp_audio.c

DESCRIPTION
    Deals with SCO in the headset.

NOTES

*/


/****************************************************************************
    Header files
*/
#include "headset_private.h"
#include "hfp_audio.h"
#include "av_stream_control.h"
#include "cvc_headset.h"
#include "headset_common.h"
#include "headset_power.h"
#include "headset_tones.h"
#include "headset_volume.h"

#include <codec.h>
#include <connection.h>
#include <hfp.h>
#include <pcm.h>
#include <panic.h>
#include <sink.h>
#include <source.h>


#ifdef DEBUG_AUDIO
#define AUDIO_DEBUG(x) DEBUG(x)
#else
#define AUDIO_DEBUG(x) 
#endif


/*****************************************************************************/
sync_pkt_type hfpGetBestScoPktType(const headsetTaskData *app)
{
    
    if (((app->supp_features_0 >>8) & 0xff) & 0x20)
        return sync_hv3;
    else if (((app->supp_features_0 >>8) & 0xff) & 0x10)
        return sync_hv2;
    else
        return sync_hv1;
}


/*****************************************************************************/
bool hfpSetupScoRouting(headsetTaskData *app)
{
   if (!SinkIsValid(app->sco_sink) || !SourceIsValid(StreamSourceFromSink(app->sco_sink)))
       return FALSE;
   
   if (isTonePlaying(app->pcm_audio_state))
   {
       setPcmState(app, pcm_tone_to_sco);
       AUDIO_DEBUG(("AUDIO: Tone playing\n"));
       return FALSE;
   }
   else
   {
       setPcmState(app, pcm_sco);
   }
   
   /* Make sure amp is powered on */
   headsetPowerAmp(app, TRUE);

   AUDIO_DEBUG(("AUDIO: Route SCO\n"));
   
   /* Cancel the timer to shut down the audio amp */
   MessageCancelAll(getAppTask(), APP_AMP_IDLE_IND);
 
#ifndef INCLUDE_CVC   
   /* Set volume to mute */
   headsetUpdateVolume(app->codec_task, 0);
   
   StreamDisconnect(StreamPcmSource(0), StreamPcmSink(0)); 
   StreamDisconnect(StreamPcmSource(1), StreamPcmSink(1)); 
   
   (void) PanicFalse(PcmClearRouting(0));
   (void) PanicFalse(PcmClearRouting(1));

#ifdef WOLFSON_CODEC
   	(void) PanicFalse(PcmRateAndRoute(0, PCM_NO_SYNC, 8000, 8000, VM_PCM_EXTERNAL_I2S));
   	(void) PanicFalse(PcmRateAndRoute(1, PCM_NO_SYNC, 8000, 8000, VM_PCM_EXTERNAL_I2S));

   	(void) PanicFalse(StreamConnect(StreamSourceFromSink(app->sco_sink), StreamPcmSink(0)));
   	(void) PanicFalse(StreamConnect(StreamPcmSource(0), app->sco_sink)); 

   CodecConfigure(app->codec_task,0);
#else
   (void) PanicFalse(PcmRateAndRoute(0, PCM_NO_SYNC, (uint32) 8000, (uint32) 8000, VM_PCM_INTERNAL_A_AND_B));
   (void) PanicFalse(StreamConnect(StreamSourceFromSink(app->sco_sink), StreamPcmSink(0)));
   if (!app->mic_mute_on)
        (void) PanicFalse(StreamConnect(StreamPcmSource(0), app->sco_sink)); 

#endif
   
   /* Set volume to required level */
 	  headsetUpdateVolume(app->codec_task, app->speaker_volume.hfp_volume);
   
#else
    CvcHeadsetConnect(app);
#endif

   return TRUE;
}


/*****************************************************************************/
void hfpHeadsetHandleAudioConnectCfm(headsetTaskData *app, const HFP_AUDIO_CONNECT_CFM_T *cfm)
{
    uint16 messages_cancelled = 0;
    bool sco_routed = FALSE;
    bool send_suspend = TRUE;
    
    /* A SCO connection has been opened to this device */
    if (cfm->status == hfp_audio_connect_success)
    {   
        /* If AG only supports HV1 SCO packets then close all connected AV streams. */
        if (hfpGetBestScoPktType(app) == sync_hv1)
        {
            A2dpCloseAll(app->a2dp);
            send_suspend = FALSE;
        }
        
        /* Don't want to restart music as we now have a SCO connection */
        messages_cancelled = MessageCancelAll(&app->task, APP_MUSIC_RESTART_IND); 
        if (!messages_cancelled && (app->a2dp_state == avHeadsetA2dpStreaming))
        {
            /* If the AV audio has not already been stopped then stop it now */
            avHeadsetAvStreamStop(app, send_suspend);
        }

        /* Store the sink associated with the SCO */
        app->sco_sink = cfm->audio_sink;

        /* Switch to hfp mode */
        app->active_profile = hfp_active;

        /* Route SCO to the PCM */
        sco_routed = hfpSetupScoRouting(app);
        
        /* If in HSP mode use sco set up as an indication of active call */
        if (app->profile_connected == hfp_headset_profile)
        {
            setHfpState(app, headsetActiveCall);

            /* The spec also requires us to send our current volume level so send it */
            HfpSendSpeakerVolume(app->hsp, (uint16)app->speaker_volume.hfp_volume);
        }
    }
}


/*****************************************************************************/
void hfpHeadsetHandleAudioDisconnectInd(headsetTaskData *app)
{
    /* Power down the codec */
    CodecPowerDown(app->codec_task);
	

    /* Delay before re-starting music. Don't restart music if still an incoming call. */
    if (app->hfp_state != headsetIncomingCallEstablish)
    {
        headsetRestartAV(app);
    }

    /* Reset the SCO sink as its no longer valid */
    app->sco_sink = 0;

    /* If in HSP mode use sco disconnect as an indication of a state change */
    if ((app->profile_connected == hfp_headset_profile) && (app->hfp_state != headsetReady))
    {
        if ((app->hfp_state == headsetActiveCall) || (app->hfp_state == headsetIncomingCallEstablish))
            headsetPlayTone(app, tone_type_call_end); 
        setHfpState(app, headsetConnected);
    }
	
    /* Start the timer to shut down the audio amp */
    MessageSendLater(getAppTask(), APP_AMP_IDLE_IND, 0, AMP_IDLE_TIMER);
	app->mic_mute_on = 0;
	MessageCancelAll( &app->task , APP_MUTE_REMINDER) ;
}


/*****************************************************************************/
void hfpHeadsetTransferAudio(headsetTaskData *app, hfp_audio_transfer_direction dir)
{
    /* 
        Decide what packet type to use based on the SCO packets supported by 
        the remote end and initiate the audio transfer.
    */
    HfpAudioTransferConnection(app->hfp, dir, (sync_hv1 | sync_hv2 | sync_hv3), 0);

    if (dir == hfp_audio_to_hfp)
        /* Make sure amp is powered on */
        headsetPowerAmp(app, TRUE);
}


/****************************************************************************/
void hfpHeadsetHandleAudioConnectInd(headsetTaskData *app, const HFP_AUDIO_CONNECT_IND_T *ind)
{
    HFP *active_hfp = 0;
	
    /* Accept audio if its for a task we own */
    if ((ind->hfp == app->hfp) || (ind->hfp == app->hsp))
        active_hfp = ind->hfp;    

    if (active_hfp)
    {
        /* For now just accept the audio connection */
        HfpAudioConnectResponse(active_hfp, 1, (sync_hv1 | sync_hv2 | sync_hv3), 0);

        /* Make sure amp is powered on */
        headsetPowerAmp(app, TRUE);
    }
    else
        HfpAudioConnectResponse(active_hfp, 0, sync_hv1, 0);
}

⌨️ 快捷键说明

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