📄 ag_connect.c
字号:
msg->srch_continue = 1;
msg->new_target = 0;
msg->new_conn_server_chan = 0;
}
}
else
{
/* User specified connect as hs or hf so we'd better not try the other */
msg->srch_continue = 0;
msg->new_target = 0;
msg->new_conn_server_chan = 0;
}
agPutCmMsg(msg);
}
/*
agConnectCfm
Contains the status of the RFCOMM connection.
*/
void agConnectCfm(const CM_CONNECT_CFM_T *cfm)
{
/*
if the connect is successful and the AG is connecting to a hands-free
device the connection is not considered to be up until some AT cmds have
been exchanged. Only send cfm once this has happened. For other cases can
send confirm straight away
*/
AGState.remote_addr = cfm->addr;
/* store handles to the sink and source rfc buffers */
AGState.rfcDataIncoming = cfm->source;
AGState.rfcDataOutgoing = cfm->sink;
/* Ser the role depending on the service connected to */
if (cfm->conn_server_chan == AGState.agHsServerChan)
agSetCurrentProfile(agHeadsetProfile);
else if (cfm->conn_server_chan == AGState.agHfServerChan)
agSetCurrentProfile(agHandsFreeProfile);
else
agSetCurrentProfile(agProfileNotSet);
if (agIsCurrentlyHeadset() || cfm->status != CmConnectComplete)
agSendStatusIndToClient(cfm->addr, cfm->status);
if (agIsCurrentlyHandsFree())
agGetExtraSdpInfo();
if (cfm->status == CmConnectComplete)
{
/* check for data */
handleSourceEvent();
}
}
/*
agRfcommStatusInd
Indication of a change in the status of the RFCOMM connection.
*/
void agRfcommStatusInd(const CM_CONNECT_STATUS_IND_T *ind)
{
agSendStatusIndToClient(ind->addr, ind->status);
}
/*
agScoStatusInd
Send the client the reported status of the SCO connection.
*/
void agScoStatusInd(const CM_SCO_STATUS_IND_T *ind)
{
if(ind->status == CmConnectComplete)
{
/* SCO created so change the AG state accordingly */
agSetCurrentState(AgScoConnected);
/* stop the ring tones */
AGState.rings_outstanding = 0;
}
else if (ind->status == CmConnectDisconnect)
{
/* SCO disconnected */
if (agScoConnectedQuery())
agSetCurrentState(AgConnected);
else
agSetCurrentState(AgIdle);
/* stop the ring tones */
AGState.rings_outstanding = 0;
/* Inform the hands-free of the change in call status */
if (agIsCurrentlyHandsFree())
agSendCallInd(0);
}
else
{
/* SCO creation attempt timed out or was cancelled */
agSetCurrentState(AgConnected);
}
/* Inform the interface that the SCO status has changed */
handleScoStatusInd(agGetConnectionHandle(&ind->addr), connectStatus(ind->status), ind->sco_handle);
}
/*
agCreateSco
Send the actual create SCO message to the CM, this way a SCO can
be created internally by the AG i.e. without a cmd from the GUI.
*/
void agCreateSco(BD_ADDR_T addr, pkt_type_t pkt)
{
/* check if an RFCOMM connection exists and if not signal an error */
if (AGState.currentState == AgConnected)
{
/*
Stop sending ring alerts - this is to handle the case
where the AG sends rings and then sets up the SCO itself
(without receiving a button press or anything similar from
the hs) should only apply to testing though.
*/
agStopRings();
{
/* AG is not in park mode so continue with the SCO creation */
MAKE_MSG(CM_SCO_CONNECT_REQ);
msg->addr = addr;
msg->pkt_type = pkt;
agPutCmMsg(msg);
}
}
else
{
/*
Cannot create a SCO unless an RFCOMM connection to that
device has been set up.
*/
agSendErrorToClient(AgErrorScoRequestWhenNotConnected, &addr);
}
}
/*
agScoConnectReqAction
Request to create a SCO connection.
*/
void agScoConnectReqAction(ag_handle_t handle, pkt_type_t type)
{
handle = handle;
agCreateSco(AGState.remote_addr, type);
}
/*
agRfcommDisconnectReqAction
Request to disconnect an RFCOMM connection.
*/
void agRfcommDisconnectReqAction(ag_handle_t handle)
{
handle = handle;
if (agRfcommConnectedQuery())
{
/* Inform the hands-free of the change in call status */
if (agIsCurrentlyHandsFree())
agSendServiceInd(0);
/*
Make sure that there is an RFCOMM and/or SCO connection
brfore trying to disconnect it. If there is a SCO up it
will be disconnected before the RFCOMM is dropped.
*/
{
MAKE_MSG(CM_DISCONNECT_REQ);
msg->link_type = RfcommConnection;
msg->addr = AGState.remote_addr;
agPutCmMsg(msg);
}
}
else
{
/* No RFCOMM connection to disconnect */
agSendErrorToClient(AgErrorRfcommNotConnected, &(AGState.remote_addr));
}
}
/*
agScoDisconnectReqAction
Request to disconnect a SCO connection
*/
void agScoDisconnectReqAction(ag_handle_t handle)
{
handle = handle;
if (agScoConnectedQuery())
{
/* Check a SCO exists before trying to disconnect it */
MAKE_MSG(CM_DISCONNECT_REQ);
msg->link_type = ScoConnection;
msg->addr = AGState.remote_addr;
agPutCmMsg(msg);
}
else
{
/* Signal an error that there is no SCO to disconnect */
agSendErrorToClient(AgErrorScoNotConnected, &(AGState.remote_addr));
}
}
/*
agSendStatusIndToClient
Send the client the reported status of the RFCOMM connection.
*/
void agSendStatusIndToClient(BD_ADDR_T dev_addr, connect_status_t status)
{
/* get the connection handle */
ag_handle_t hdl = agGetConnectionHandle(&dev_addr);
ag_profile_role_t role = agProfileNotSet;
if (status == CmConnectComplete)
{
agSetCurrentState(AgConnected);
if (agIsCurrentlyHeadset())
role = agHeadsetProfile;
else if (agIsCurrentlyHandsFree())
role = agHandsFreeProfile;
else
role = agProfileNotSet;
}
else
{
/*
If connection has been disconnected or connect attempt
abandoned/ failed then remove the remote device address
from the handle map. A new handle will be allocated if the
ag tries to connect to that device at some later time
*/
removeAddressFromHandleMap(hdl);
/* AG is in idle mode */
agSetCurrentState(AgIdle);
/* Disable status flags */
AGState.hfIndicatorUpdateEnabled = 0;
AGState.hfVoiceRecogEnable = 0;
/* cancel any ring tones being sent */
agStopRings();
}
/* inform the interface of the change in rfcomm connection status */
handleRfcommStatusInd(hdl, connectStatus(status), role);
}
/* --------------------------------------------------------------------------
Internally called functions to handle device address to ag_handle mapping
--------------------------------------------------------------------------
*/
/*
createAddressHandleMap
Allocate the array used to produce device address to ag_handles map.
*/
void createAddressHandleMap(void)
{
AGState.remote_addr.lap = 0;
AGState.remote_addr.uap = 0;
AGState.remote_addr.nap = 0;
}
/*
agGetConnectionHandle
Given a device address return the handle corresponding to it in
the map If an entry does not exist for the device address return
UNDEFINED_HANDLE.
*/
ag_handle_t agGetConnectionHandle(const BD_ADDR_T *addr)
{
if (AGState.remote_addr.lap == addr->lap &&
AGState.remote_addr.uap == addr->uap &&
AGState.remote_addr.nap == addr->nap)
return ONLY_ONE_HANDLE;
else
return UNDEFINED_HANDLE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -