📄 hfp_audio.c
字号:
/****************************************************************************
Copyright (C) Cambridge Silicon Radio Ltd. 2004-2006
Part of BlueLab 3.6.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 "headset_codec.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>
#include <stdlib.h>
#include <audio.h>
#include <csr_cvc_plugin.h>
#include <csr_no_dsp_plugin.h>
#include <csr_sco_dsp_plugin.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)
{
AUDIO_MODE_T lMode = AUDIO_MODE_CONNECTED ;
/* Make sure amp is powered on */
headsetPowerAmp(app, TRUE);
DEBUG(("ScoSink:[%x]\n", (int)app->sco_sink)) ;
PanicFalse(app->sco_sink) ;
if (app->voice_recognition_enabled)
{
lMode = AUDIO_MODE_MUTE_SPEAKER ;
}
#ifdef INCLUDE_CVC
AudioConnect ( (TaskData*) &csr_cvc_plugin, app->sco_sink , app->codec_task , app->speaker_volume.hfp_volume , TRUE , lMode , NULL ) ;
#else
AudioConnect ( (TaskData*) &csr_no_dsp_plugin, app->sco_sink , app->codec_task , app->speaker_volume.hfp_volume , TRUE , lMode , NULL ) ;
#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)
{
/* Reset the SCO sink as its no longer valid */
app->sco_sink = 0;
AudioDisconnect() ;
/* Power down the codec */
CodecPowerDown(app->codec_task);
/* Delay before re-starting music. Don't restart music if still an incoming call or an outgoing call */
if ((app->hfp_state != headsetIncomingCallEstablish) && (app->hfp_state != headsetOutgoingCallEstablish))
{
headsetRestartAV(app);
}
/* 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);
}
app->mic_mute_on = FALSE;
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.
*/
#ifdef HFP_1_5
if (app->profile_connected == hfp_headset_profile)
HfpAudioTransferConnection(app->hfp, dir, (sync_all_sco), 0);
else
HfpAudioTransferConnection(app->hfp, dir, (sync_all_sco | sync_all_esco), 0);
#else
HfpAudioTransferConnection(app->hfp, dir, (sync_all_sco), 0);
#endif
}
/****************************************************************************/
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)
{
/* Accept the audio connection */
#ifdef HFP_1_5
if (app->profile_connected == hfp_headset_profile)
HfpAudioConnectResponse(active_hfp, 1, (sync_all_sco), 0);
else
HfpAudioConnectResponse(active_hfp, 1, (sync_all_sco | sync_all_esco), 0);
#else
HfpAudioConnectResponse(active_hfp, 1, (sync_all_sco), 0);
#endif
/* 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 + -