⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ag_connect.c

📁 bluetooth audio gateway
💻 C
📖 第 1 页 / 共 2 页
字号:
			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 + -