📄 headset_slc.c
字号:
/****************************************************************************
Copyright (C) Cambridge Silicon Radio Ltd. 2004
FILE NAME
headset_slc.c
DESCRIPTION
NOTES
*/
/****************************************************************************
Header files
*/
#include "headset_private.h"
#include "headset_scan.h"
#include "headset_slc.h"
#include "headset_statemanager.h"
#include "headset_configmanager.h"
#include "headset_soundmanager.h"
#include "headset_callmanager.h"
#include <connection.h>
#include <hfp.h>
#include <panic.h>
#include <ps.h>
#include <bdaddr.h>
#ifdef DEBUG_SLC
#define SLC_DEBUG(x) DEBUG(x)
#ifdef DEBUG_PRINT_ENABLED
static const char * const gDebugReconStrings[7] = { "AR_LastConnected",
"AR_Last",
"AR_Default",
"AR_LastThenDefault",
"AR_DefaultThenLast",
"AR_Swap",
"AR_SwapSwap"
};
#endif
#else
#define SLC_DEBUG(x)
#endif
typedef enum NextPagingTag
{
PageUnknown ,
PageLastAG ,
PageDefaultAG ,
PageComplete
}NextPage_t;
typedef enum CurrPagingTag
{
PagingLast ,
PagingDefault
}CurrPaging_t ;
typedef enum LastConnectedTag
{
LastNone ,
LastDefault ,
LastLast
}LastConnected_t ;
typedef struct slcDataTag
{
unsigned gNextPage:2;
unsigned gLastConnected:2;
unsigned gCurrPaging:1;
unsigned gCallTransferInProgress:1 ;
unsigned gLinkLossOccured:10;
}slcData_t;
static slcData_t gSlcData = {PageUnknown, LastNone, PagingLast , FALSE, FALSE} ;
static void slcAttemptConnect ( hsTaskData *pApp, hfp_profile pProfile , bdaddr * pAddr) ;
static void slcConnectDefaultAG ( hsTaskData * pApp , hfp_profile pProfile ) ;
static void slcConnectLastAG ( hsTaskData * pApp , hfp_profile pProfile ) ;
static void slcConnectLastConnectedAG( hsTaskData * pApp , hfp_profile pProfile ) ;
static void slcProfileConnected (hsTaskData * pApp , HFP * pProfile, Sink sink ) ;
static void slcHandleSlcConnectRequest(hsTaskData *app, hfp_profile profile , ARAction_t pAction );
#define SLC_LINK_LOSS_RETRY_TIME_SECS 10
/****************************************************************************
NAME
slcConnectFail
DESCRIPTION
SLC failed to connect
RETURNS
void
*/
static void slcConnectFail(hsTaskData *app)
{
/* Update the app state */
SLC_DEBUG(("SLC : det Pairing Fail \n")) ;
headsetClearQueueudEvent ( app ) ;
/*
stateManagerEnterConnectableState( app ) ;
*/
/* No connection */
app->profile_connected = hfp_no_profile;
if (gSlcData.gLinkLossOccured)
{
SLC_DEBUG(("SLC: LinkLoss [%x]\n" , gSlcData.gLinkLossOccured)) ;
MessageSendLater (&app->task , EventLinkLoss, 0 , D_SEC(SLC_LINK_LOSS_RETRY_TIME_SECS) ) ;
/*attempts for n attempts until = 0 */
gSlcData.gLinkLossOccured-- ;
}
else
{
if ( (gSlcData.gNextPage == PageComplete ) || (gSlcData.gNextPage == PageUnknown) )
{
/*then we have completed our PSKEY defined page routine unsuccessfully so reset for next time round*/
/*or we are in the unknown state as we were attempting to reconnect after a link loss - leave reset*/
gSlcData.gNextPage = PageUnknown ;
/* As we have failed to conenct to an AG - its as if we have just powered on*/
/* JM01 - However, power on action maybe different to disconnect action */
#if 0
gSlcData.gLastConnected = LastNone;
#endif
}
else
{
/*then page something else */
MessageSend ( &app->task , EventEstablishSLC , 0 ) ;
}
}
}
/****************************************************************************
NAME
headsetHandleSlcConnectInd
DESCRIPTION
Handle a request to establish an SLC from the AG.
RETURNS
void
*/
void headsetHandleSlcConnectInd(hsTaskData *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);
/* 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);
}
gSlcData.gLinkLossOccured = 0 ;
}
/****************************************************************************
NAME
headsetHandleSlcConnectCfm
DESCRIPTION
Confirmation that the SLC has been established (or not).
RETURNS
void
*/
bool headsetHandleSlcConnectCfm(hsTaskData *app, const HFP_SLC_CONNECT_CFM_T *cfm)
{
bool lResult = FALSE ;
/* Check the status of the SLC attempt */
if (cfm->status == hfp_connect_success)
{
slcProfileConnected(app, cfm->hfp, cfm->sink);
lResult = TRUE ;
gSlcData.gLinkLossOccured = 0 ;
}
else if (cfm->status == hfp_connect_sdp_fail)
{
/* We failed to find the hfp profile */
if (cfm->hfp == app->hfp)
{
/* Didn't find HFP so try HSP */
SLC_DEBUG(("SLC: CFM HFP Fail - Try HSP\n")) ;
if ( gSlcData.gCurrPaging == PagingLast )
{
slcConnectLastAG ( app , hfp_headset_profile ) ;
}
else
{
slcConnectDefaultAG ( app , hfp_headset_profile ) ;
}
}
else if (cfm->hfp == app->hsp)
{
SLC_DEBUG(("SLC: CFP HSP Fail\n")) ;
/* We try the HSP after we've tried HFP so this AG supports neither, give up */
slcConnectFail(app);
}
else
/* Unknown profile instance */
Panic();
}
else
{
/* Update local state to reflect this */
slcConnectFail(app);
}
return lResult ;
}
/****************************************************************************
NAME
slcHandleSlcConnectRequest
DESCRIPTION
Request to create a connection to a remote AG. This could have occured for several
reasons
- if we have just powerered on and are configured to auto connect
- if we have failed to reconnect to the first device that we tried to connect to
- if we have had a button event requesting connection
- if we have had a link loss and wish to recover the last AG connected
RETURNS
void
*/
static void slcHandleSlcConnectRequest(hsTaskData *pApp, hfp_profile pProfile , ARAction_t pAction )
{
if ( pAction == AR_LastConnected)
{
slcConnectLastConnectedAG (pApp, hfp_handsfree_profile);
}
else
{
switch (gSlcData.gNextPage)
{
case ( PageUnknown ): /* we are at the start of the pattern*/
{
switch ( pAction )
{
case AR_Last:
gSlcData.gNextPage = PageComplete ;
slcConnectLastAG ( pApp , pProfile ) ;
SLC_DEBUG(("SLC: Page Last Only\n")) ;
break ;
case AR_Default:
gSlcData.gNextPage = PageComplete ;
slcConnectDefaultAG ( pApp , pProfile ) ;
SLC_DEBUG(("SLC: Page Def Only\n")) ;
break ;
case AR_LastThenDefault:
gSlcData.gNextPage = PageDefaultAG ;
slcConnectLastAG ( pApp , pProfile ) ;
SLC_DEBUG(("SLC: Page1 Last\n")) ;
break ;
case AR_DefaultThenLast:
gSlcData.gNextPage = PageLastAG ;
slcConnectDefaultAG ( pApp , pProfile ) ;
SLC_DEBUG(("SLC: Page1 Def\n")) ;
break ;
default:
break ;
}
}
break ;
case (PageDefaultAG ):
{
gSlcData.gNextPage = PageComplete ;
slcConnectDefaultAG ( pApp , pProfile ) ;
SLC_DEBUG(("SLC:Page2 Def\n")) ;
}
break ;
case (PageLastAG ):
{
gSlcData.gNextPage = PageComplete ;
slcConnectLastAG ( pApp , pProfile ) ;
SLC_DEBUG(("SLC:Page1 Last\n")) ;
}
break;
default:
/*Paging attempts as per PSKEY's complete*/
break ;
}
}
}
/* Methods to connect to the last or default AG's*/
static void slcConnectDefaultAG ( hsTaskData * pApp , hfp_profile pProfile )
{
bdaddr lDefaultAddr ;
/* Retrieve the address of the default AG from PS */
if ( sizeof(bdaddr) == PsRetrieve(PSKEY_DEFAULT_AG, &lDefaultAddr, sizeof(bdaddr) ) )
{
SLC_DEBUG(("SLC: Att Def[%x]\n" , pProfile)) ;
slcAttemptConnect ( pApp , pProfile , &lDefaultAddr ) ;
gSlcData.gCurrPaging = PagingDefault ;
}
else
{ /* we have failed to connect as we don't have a valid address */
SLC_DEBUG(("SLC: No Default Addr \n")) ;
slcConnectFail (pApp);
}
}
static void slcConnectLastAG ( hsTaskData * pApp , hfp_profile pProfile )
{
bdaddr lLastAddr ;
/* Retrieve the address of the last used AG from PS */
if (sizeof(bdaddr) == PsRetrieve(PSKEY_LAST_USED_AG, &lLastAddr, sizeof(bdaddr)))
{
SLC_DEBUG(("SLC: Att Last[%x]\n" , pProfile)) ;
slcAttemptConnect ( pApp , pProfile , &lLastAddr ) ;
gSlcData.gCurrPaging = PagingLast ;
}
else
{ /* we have failed to connect as we don't have a valid address */
SLC_DEBUG(("SLC: No Last Addr \n")) ;
slcConnectFail (pApp);
}
}
static void slcConnectLastConnectedAG( hsTaskData * pApp , hfp_profile pProfile )
{
switch (gSlcData.gLastConnected)
{
case LastDefault:
slcConnectDefaultAG( pApp , pProfile) ;
break;
case LastLast:
slcConnectLastAG( pApp , pProfile) ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -