📄 connect.c
字号:
#include "handsfree_private.h"
#include "handsfree.h"
#include <cm_rfcomm.h>
#include <message.h>
#include <print.h>
#include <stdlib.h>
/*
Specify the park and sniff parameters. To disable either mode
use zero as the value for the intervals.
*/
static void default_park(cm_park_config_t *park)
{
/* Set the max park interval to 1.28s min to 100ms */
park->max_intval = 0x800;
park->min_intval = 0x100;
}
static void default_sniff(cm_sniff_config_t *sniff)
{
/* Set the max sniff interval to 40ms and min to 20ms */
sniff->max_intval = 0x40;
sniff->min_intval = 0x20;
sniff->attempt = 0x01;
sniff->timeout = 0x00;
}
/*
connectMaster
Internal function to request framework to connect as master using the
specified parameters.
*/
static void connectMaster(Delay timeout)
{
/* Create a headset connect message primitive */
MAKE_MSG(HS_CONNECT_AS_MASTER_REQ) ;
msg->timeout = timeout ;
default_park(&msg->park);
default_sniff(&msg->sniff);
putMsg(msg) ;
setLocalState(connectingAsMaster);
}
/*
connectSlave
Internal function to request framework to connect as slave using the
specified parameters.
*/
static void connectSlave(Delay timeout, /* How long to attempt connection (paging) */
uint16_t psinterval, /* page scan interval */
uint16_t pswindow, /* page scan window */
uint16_t isinterval, /* inquiry scan interval */
uint16_t iswindow) /* inquiry scan window */
{
MAKE_MSG(HS_CONNECT_AS_SLAVE_REQ) ;
msg->timeout = timeout ;
default_park(&msg->park);
default_sniff(&msg->sniff);
msg->ps_interval = psinterval ; /* page scan interval */
msg->ps_window = pswindow ; /* page scan window */
msg->is_interval = isinterval; /* inquiry scan interval */
msg->is_window = iswindow; /* inquiry scan window */
putMsg(msg) ;
setLocalState(connectingAsSlave);
}
/*
connectReqAction
Attempt to connect to the device paired with as either master or
slave.
*/
void connectReqAction(void)
{
switch (HFstate.connectState)
{
/*
Hands-free is idle, attempt to connect to the Audio
Gateway which is the only paired device. Initiating the
connection means the hands-free is the master.
*/
case idle :
connectSlave(SLAVE_CONNECT_TIMEOUT, 0x800, 0x12, 0x400, 0x200) ;
break ;
/*
If the handsfree is already attempting to connect as the
master, cancel the operation and return to idle state.
*/
case connectingAsMaster :
cancelCurrentStateAction() ;
HFstate.connectAsMasterPending = 0 ;
break ;
/*
If the hands-free is already attempting to connect as the
slave, cancel the operation and attempt to connect as
master.
*/
case connectingAsSlave :
HFstate.connectAsMasterPending = 1 ;
cancelCurrentStateAction(); /* return to idle */
break ;
/*
If the hands-free is currently attempting to pair, reject
the button press because it cannot do anything until it is
paired with the Audio Gateway.
*/
case pairing :
/* CAnnot connect whilst pairing */
handleErrorInd(HfErrorConnectRequestWhenNotIdle);
break ;
default:
PRINT(("connect.c - talkbutton() - invalid state: 0x%2x\n",
HFstate.connectState));
handleErrorInd(HfErrorUnknownOrUnhandledState);
break ;
}
}
/*
hfConnectCfm
After sending a connectReq, we expect to see a confirm. If the
connection was successful we may need to send a button press,
otherwise we just return to idle.
*/
void hfConnectCfm(const HS_CONNECT_CFM_T * cfm)
{
/* reset the current role */
HFstate.applicationRole = frameworkRoleUnset;
/* Take action based on the outcome of the connection process. */
switch (cfm->status)
{
/* The connection has been completed */
case CmConnectComplete :
{
uint16 old_connect_state = HFstate.connectState;
/*
Workaround, in case AG opens SCO before SLC is established
(out of HFP spec but it happens)
*/
if (old_connect_state == scoConnected)
{
/* Set back to SCO connected since it was reset to idle above */
setLocalState(scoConnected);
/* Reset the pending flag, the AG has already opened the SCO */
HFstate.audioTransferPending = 0;
}
else
{
/* Set the headset state to indicate it is connected */
setLocalState(connected);
}
/* store and check the role we have connected as */
HFstate.applicationRole = cfm->profile_role;
if (HFstate.applicationRole == frameworkHandsFree)
{
/* Check if there is a dial request pending */
hfCheckDialPendingFlags();
/* Check if there was an audio transfer event pending */
if (HFstate.audioTransferPending)
callTransferReqAction(HFstate.SCOpktType);
/* Check if voice dialling is pending */
if (HFstate.voiceDialPending)
startVoiceDialAction(1);
/* TODO on exiting here none of the pending flags must be set
TODO above it should be an "else if" becuase only one
pending flag should be set.
*/
}
/* Let the interface app do what it will */
handleConnectComplete();
}
break ;
/* If the connection was cancelled, maybe we are just switching roles */
case CmConnectCancelled:
/* Update the local state to idle */
setLocalState(idle);
/* Check if we are trying to switch from a slave to a master. */
if (HFstate.connectAsMasterPending)
{
/*
Reset the connect as slave pending flag to false
because we are actually connecting now...no longer
pending.
*/
HFstate.connectAsMasterPending = 0 ;
/* Resend the connect command with new values*/
connectMaster(MASTER_CONNECT_TIMEOUT);
}
else if (HFstate.pair_data)
{
/* Request to enter pairing mode */
pairReqAction(HFstate.pair_data->pairing_timeout, HFstate.pair_data->pairing_role);
/* If we had stored pairing data free it as its no longer needed */
if (HFstate.pair_data)
free(HFstate.pair_data);
HFstate.pair_data = 0;
}
else
{
/* Default to slave connect mode */
connectReqAction();
}
break ;
/* For all other connection results, jump to idle state */
case CmConnectTimeout:
case CmConnectDisconnect:
case CmConnectDisconnectAbnormal:
case CmConnectRemoteRefusal:
case CmConnectServiceNotSupported:
case CmConnectFailed:
/* Update the local state to idle */
setLocalState(idle);
/* Make sure we free any allocated memory */
hfResetConnectionState();
/* Default to slave connect mode */
connectReqAction();
break;
default:
/* Update the local state to idle */
setLocalState(idle);
PRINT(("handleConnectCfm: unhandled connect state %d\n", cfm->status));
handleErrorInd(HfErrorUnknownOrUnhandledState);
break ;
}
}
/*
handleConnectStatusInd
Called by the headset framework to indicate that the RFCOMM
connection has changed state. At the moment, this can only ever
be for rfcomm going down.
*/
void hfConnectStatusInd(HS_CONNECT_STATUS_IND_T * ind)
{
ind = ind ; /* not using this right now. Just avoiding warnings */
/*
Since this function is only called when the RFCOMM connection is
lost, indicate that there is no connection by setting the hands-free
state to idle
*/
setLocalState(idle);
/* Reset all state that may have been set during the connection */
hfResetConnectionState();
/* Default to slave connect mode */
connectReqAction();
}
/*
hfSendDisconnectMessage
Create a disconnect message and send it
*/
void hfSendDisconnectMessage(hf_link_type_t link)
{
MAKE_MSG(HANDSFREE_DISCONNECT_REQ);
msg->connectionType = (link_type_t) link;
putMsg(msg);
}
/*
disconnectReqAction
Send a disconnect request to disconnect the SCO (if up) or the
RFCOMM connection (this also releases the SCO if one exists.)
*/
void disconnectReqAction(hf_link_type_t link)
{
if (isLocalStateConnected())
{
/* Check which type of link to disconnect. */
if (link == ScoLink)
hfSendDisconnectMessage(ScoLink);
else
hfSendDisconnectMessage(RfcommLink);
}
else
{
/* Not connected so send up an error */
handleErrorInd(HfErrorDisconnectRequestWhenNotConnected);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -