📄 headset_hfp_handler.c
字号:
/****************************************************************************
Copyright (C) Cambridge Silicon Radio Ltd. 2004-2007
FILE NAME
headset_hfp_handler.c
DESCRIPTION
Functions which handle the HFP library messages.
*/
#include "headset_a2dp_stream_control.h"
#include "headset_amp.h"
#include "headset_debug.h"
#include "headset_hfp_handler.h"
#include "headset_hfp_slc.h"
#include "headset_init.h"
#include "headset_LEDmanager.h"
#include "headset_statemanager.h"
#include "headset_tones.h"
#include "headset_volume.h"
#include <audio.h>
#include <csr_no_dsp_plugin.h>
#include <csr_cvc_plugin.h>
#include <hfp.h>
#include <panic.h>
#include <pio.h>
#include <stdlib.h>
#ifdef DEBUG_HFP
#define HFP_DEBUG(x) DEBUG(x)
#else
#define HFP_DEBUG(x)
#endif
/****************************************************************************
LOCAL FUNCTION PROTOTYPES
*/
static bool audioConnectSco ( hsTaskData *pApp );
/****************************************************************************
HFP MESSAGE HANDLING FUNCTIONS
*/
/****************************************************************************/
void hfpHandlerInitCfm( hsTaskData * pApp , const HFP_INIT_CFM_T *cfm )
{
/* Make sure the profile instance initialisation succeeded. */
if (cfm->status == hfp_init_success)
{
/* Check for an hfp instance, that's registered first */
if (!pApp->hfp)
{
/* This must be the hfp instance */
pApp->hfp = cfm->hfp;
}
else
{
/* Its not HFP so must be HSP */
pApp->hsp = cfm->hfp;
/* HFP/HSP Library initialisation was a success, initailise the
A2DP library. */
InitA2dp();
}
}
else
/* If the profile initialisation has failed then things are bad so panic. */
Panic();
}
/****************************************************************************/
void hfpHandlerConnectInd( hsTaskData * pApp , const HFP_SLC_CONNECT_IND_T *ind )
{
/* Don't handle this message if the headset is powered off */
if (stateManagerGetHfpState() == headsetPoweringOn)
return;
/* We support more than one HFP so check which one this request is for */
if (pApp->profile_connected == hfp_no_profile)
{
HfpSlcConnectResponse(ind->hfp, 1, &ind->addr, 0);
/* See whether we are connecting as HSP or HFP */
if (ind->hfp == pApp->hfp)
{
pApp->profile_connected = hfp_handsfree_profile;
}
else if (ind->hfp == pApp->hsp)
{
pApp->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);
}
}
/****************************************************************************/
void hfpHandlerConnectCfm( hsTaskData * pApp , const HFP_SLC_CONNECT_CFM_T *cfm )
{
if (stateManagerGetHfpState() == headsetPoweringOn)
{
if ( cfm->status == hfp_connect_success )
{
/* A connection has been made and we are now logically off */
hfpSlcDisconnect( pApp );
}
pApp->slcConnecting = FALSE;
pApp->slcConnectFromPowerOn = FALSE;
return;
}
if (cfm->status == hfp_connect_success)
{
hfpSlcConnectSuccess(pApp, cfm->hfp, cfm->sink);
}
else if (cfm->status == hfp_connect_sdp_fail)
{
if ( !stateManagerIsHfpConnected() ) /*only continue if not already connected*/
{
if (cfm->hfp == pApp->hfp)
{
/* Didn't find HFP so try HSP */
hfpSlcConnectRequest ( pApp , hfp_headset_profile );
}
else if (cfm->hfp == pApp->hsp)
{
HFP_DEBUG(("SLC: CFM HSP Fail\n")) ;
/* We try the HSP after we've tried HFP so this AG supports neither, give up */
hfpSlcConnectFail(pApp);
}
else
{
Panic();/* Unknown profile instance */
}
}
else
{
pApp->slcConnecting = FALSE;
pApp->slcConnectFromPowerOn = FALSE;
}
}
else
{
if ( !stateManagerIsHfpConnected() ) /*only continue if not already connected*/
{ /* Failed to connect */
hfpSlcConnectFail(pApp);
}
else
{
pApp->slcConnecting = FALSE;
pApp->slcConnectFromPowerOn = FALSE;
}
}
}
/*****************************************************************************/
void hfpHandlerDisconnectInd(hsTaskData * pApp, const HFP_SLC_DISCONNECT_IND_T *ind)
{
pApp->slc_sink = 0;
/* Store current volume levels to ensure correct values on next SLC connect */
VolumeStoreLevels(pApp);
/* Check if this was the result of an abnormal link loss */
if (ind->status == hfp_disconnect_link_loss )
{
HFP_DEBUG(("HFP: Link Loss Detect\n")) ;
MessageSend( &pApp->task , EventLinkLoss , 0 ) ;
if (!stateManagerIsA2dpStreaming())
/* A Link Loss has occured - attempt reconnect */
hfpSlcConnectRequest( pApp , hfp_handsfree_profile ) ;
}
else
{
/* A disconnect in active call state is a call transfer */
if ( (stateManagerGetHfpState() == headsetActiveCall) )
{
/*slcCallTransferInProgress( app) ; */
}
else
{
/*slcCallTransferNotInProgress( app) ;*/
}
}
/*
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 ((pApp->profile_connected == hfp_headset_profile))
{
streamControlResumeA2dpStreaming(pApp, 0);
}
/* Update the app state if we are connected */
if ( stateManagerIsHfpConnected() )
{
stateManagerEnterHfpConnectableState( pApp, FALSE ) ;
}
MessageSend(&pApp->task , EventSLCDisconnected , 0) ;
/* Connection disconnected */
pApp->profile_connected = hfp_no_profile;
/* Reset in-band ring tone support flag */
pApp->InBandRingEnabled = FALSE;
PROFILE_MEMORY(("HFPDisco"))
}
/*****************************************************************************/
void hfpHandlerInbandRingInd( hsTaskData * pApp, const HFP_IN_BAND_RING_IND_T * ind )
{
pApp->InBandRingEnabled = ind->ring_enabled;
}
/*****************************************************************************/
void hfpHandlerCallInd ( hsTaskData *pApp, const HFP_CALL_IND_T * pInd )
{
switch (pInd->call)
{
case 0:
if ( stateManagerGetHfpState() == headsetActiveCall )
{
stateManagerEnterHfpConnectedState ( pApp ) ;
}
break;
case 1:
stateManagerEnterActiveCallState ( pApp ) ;
break;
default:
break;
}
}
/*****************************************************************************/
void hfpHandlerCallSetupInd ( hsTaskData *pApp, const HFP_CALL_SETUP_IND_T * pInd )
{
switch (pInd->call_setup)
{
case (hfp_no_call_setup): /*!< No call currently being established.*/
/* Spec says that this is a clear indication that an incoming call has been interrupted
and we can assume that the call is not going to continue....*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -