?? hfp_headset_slc.c
字號:
/****************************************************************************
Copyright (C) Cambridge Silicon Radio Ltd. 2004
FILE NAME
hfp_headset_slc.c
DESCRIPTION
NOTES
*/
/****************************************************************************
Header files
*/
#include "headset_private.h"
#include "headset_scan.h"
#include "hfp_headset_sco.h"
#include "hfp_headset_slc.h"
#include "hfp_headset_ring.h"
#include "av_headset_controls.h"
#include "av_headset_kalimba.h"
#include <connection.h>
#include <hfp.h>
#include <panic.h>
#include <ps.h>
static void slcConnectFail(headsetTaskData *app)
{
/* Update the app state */
app->hfp_state = headsetReady;
/* No connection */
app->profile_connected = hfp_no_profile;
/* Cancel button presses */
(void) MessageCancelAll(&app->task, BUTTON_PLAY_PAUSE_LONG);
(void) MessageCancelAll(&app->task, BUTTON_STOP_LONG);
if (app->button_action_pending_lock > 1)
{
MessageSend(getAppTask(), APP_HFP_SLC_REQ, 0);
}
else
{
(void) MessageCancelAll(getAppTask(), APP_HFP_SLC_TIMEOUT_IND);
app->button_action_pending_lock = 0;
}
if (app->av_stream_stopped && !app->sco_sink)
{
hfpHeadsetPlayRingTone(app, error_tone);
}
}
/****************************************************************************
NAME
hfpHeadsetHandleSlcConnectInd
DESCRIPTION
Handle a request to establish an SLC from the AG.
RETURNS
void
*/
void hfpHeadsetHandleSlcConnectInd(headsetTaskData *app, const HFP_SLC_CONNECT_IND_T *ind)
{
/* We support more than one HFP so check which one this request is for */
/*
TODO B-4373 we probably want to be a bit more fussy here but for now accept
the connection for whichever profile instance is specified in the message
*/
if (app->profile_connected == hfp_no_profile)
{
HfpSlcConnectResponse(ind->hfp, 1, &ind->addr, 0);
/* Update the app state */
app->hfp_state = headsetConnecting;
/* 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);
}
}
/****************************************************************************
NAME
hfpHeadsetHandleSlcConnectCfm
DESCRIPTION
Confirmation that the SLC has been established (or not).
RETURNS
void
*/
void hfpHeadsetHandleSlcConnectCfm(headsetTaskData *app, const HFP_SLC_CONNECT_CFM_T *cfm)
{
/* TODO: B-4373 how do we support multiple instances */
/* Check the status of the SLC attempt */
if (cfm->status == hfp_connect_success)
{
bdaddr ag_addr;
/* Update the app state */
if (app->hfp_state == headsetConnecting)
app->hfp_state = headsetConnected;
(void) MessageCancelAll(getAppTask(), APP_HFP_SLC_TIMEOUT_IND);
app->button_action_pending_lock = 0;
headsetTestForConnectablilty(app);
/* Read the remote supported features of the AG */
ConnectionReadRemoteSuppFeatures(getAppTask(), cfm->sink);
/* Store the address as the last used AG which can be obtained from the sink */
if (SinkGetBdAddr(cfm->sink, &ag_addr))
(void) PsStore(LAST_USED_AG, &ag_addr, sizeof(bdaddr));
/* If there is a pending APP_MUSIC_RESTART_IND message then it must have
been sent because there was HFP link-loss and the AV stream was suspended
while the headset tried to reconnect back to the AG, to stop any AV stuttering.
As the HFP connect has been a success, the AV can be restarted now.
*/
if (MessageCancelAll(getAppTask(), APP_MUSIC_RESTART_IND))
MessageSend(getAppTask(), APP_MUSIC_RESTART_IND, 0);
/*
The sink is no longer valid, this could happen if the device connects
and disconnects very quickly. For now ignore, the disconnect message
should arrive shortly.
*/
}
else if (cfm->status == hfp_connect_sdp_fail)
{
/* We failed to find the requested profile */
if (cfm->hfp == app->hfp)
{
/* Didn't find HFP so try HSP */
hfpHeadsetHandleSlcConnectRequest(app, hfp_headset_profile);
}
else if (cfm->hfp == app->hsp)
{
/* 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);
}
}
/****************************************************************************
NAME
hfpHeadsetHandleSlcConnectRequest
DESCRIPTION
Request to create a connection to a remote AG.
RETURNS
void
*/
void hfpHeadsetHandleSlcConnectRequest(headsetTaskData *app, hfp_profile profile)
{
bdaddr addr;
/* Set up the extra indicator config
const char *inds = "roam\rbattchg\rchargerconnected\rflobber\r"; */
/* Retrieve the address of the last used AG from PS */
if (!PsRetrieve(LAST_USED_AG, &addr, sizeof(bdaddr)))
{
/* Play an error tone to indicate we don't have a valid address */
slcConnectFail(app);
return;
}
/* Update the app state */
app->hfp_state = headsetConnecting;
if (profile == hfp_handsfree_profile)
{
app->profile_connected = hfp_handsfree_profile;
/* Issue a connect request for HFP */
HfpSlcConnect(app->hfp, &addr, 0);
}
else if (profile == hfp_headset_profile)
{
app->profile_connected = hfp_headset_profile;
/* Issue a connect request for HFP */
HfpSlcConnect(app->hsp, &addr, 0);
}
else
/* The app should know what profile it wants to connect as */
Panic();
}
/****************************************************************************
NAME
hfpHeadsetDisconnectSlc
DESCRIPTION
Disconnect the SLC associated with this profile instance.
RETURNS
void
*/
void hfpHeadsetDisconnectSlc(const headsetTaskData *app)
{
/* Issue the disconnect request and let the HFP lib do the rest */
HfpSlcDisconnect(app->hfp);
}
/****************************************************************************
NAME
hfpHeadsetHandleSlcDisconnectInd
DESCRIPTION
Indication that the SLC has been released.
RETURNS
void
*/
void hfpHeadsetHandleSlcDisconnectInd(headsetTaskData *app, const HFP_SLC_DISCONNECT_IND_T *ind)
{
/* 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 ((app->profile_connected == hfp_headset_profile) && app->av_stream_stopped)
{
(void) MessageCancelAll(getAppTask(), APP_MUSIC_RESTART_IND);
MessageSendLater(getAppTask(), APP_MUSIC_RESTART_IND, 0, (uint32) MUSIC_RESTART_DELAY);
}
/* Update the app state */
app->hfp_state = headsetReady;
/* Connection disconnected */
app->profile_connected = hfp_no_profile;
headsetTestForConnectablilty(app);
/* Store the latest volume setting */
(void) PsStore(VOLUME_LEVEL, &app->speaker_volume, sizeof(app->speaker_volume));
/* Procedure for abnormal link-loss */
if (ind->status == hfp_disconnect_link_loss)
{
/* If AV is streaming then Suspend it as the HFP reconnect will
cause interruptions in the audio.
*/
if (app->a2dp_state == avHeadsetA2dpStreaming)
{
avHeadsetAvStreamStop(app, TRUE);
(void) MessageCancelAll(getAppTask(), APP_MUSIC_RESTART_IND);
MessageSendLater(getAppTask(), APP_MUSIC_RESTART_IND, 0, SLC_CONNECT_TIMEOUT + 2);
}
/* Send a reconnect attempt */
app->button_action_pending_lock = 2;
MessageSend(getAppTask(), APP_HFP_SLC_REQ, 0);
/* Set the connect attempt timeout. */
MessageSendLater(getAppTask(), APP_HFP_SLC_TIMEOUT_IND, 0, SLC_CONNECT_TIMEOUT);
}
}
/****************************************************************************
NAME
headsetHandleRemoteSuppFeatures
DESCRIPTION
Supported features of the remote device contained in the message if the
read succeeded.
RETURNS
void
*/
void headsetHandleRemoteSuppFeatures(headsetTaskData *app, const CL_DM_REMOTE_FEATURES_CFM_T *cfm)
{
/*
If the read request succeeded then store the first work of the supported features
We should in theory store all four words but currently we only need the info in
the first word so for the sake of efficiency for the moment only store that.
*/
if (cfm->status == hci_success)
{
app->supp_features_0 = cfm->features[0];
/*
If we have a SCO open when we get this then we probably tried to
change the pkt type to HV1 so go and check the remote supported
features again to see if we can change to HV3.
*/
if (app->sco_sink)
ConnectionScoChangePktType(app->sco_sink, hfpGetBestScoPktType(app));
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -