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

📄 bthandsfree.cpp

📁 蓝牙
💻 CPP
字号:
#include "xlog.h"#include "btsocket.h"#include "scosocket.h"#include "bycmd.h"#include "global.h"#include "bthandsfree.h"#include "btrmtdevmgr.h"void CallbackAgApEvent(BTUINT16 event, BTUINT8* param, BTUINT32 param_len){	g_hfDev.OnAGAPPEvCbk(event, param, param_len);}void CallbackScoDataInd(BTUINT16 conn_hdl,BTUINT16 len, BTUINT8 *packet){	g_hfDev.OnScoDataInd(conn_hdl, len, packet);}HandsFree::HandsFree(){	m_hDev = BTSDK_INVALID_HANDLE;	m_hAGConn = BTSDK_INVALID_HANDLE;	m_nSpkVol = 10;	m_nAgState = AG_STATE_NULL;	m_bAGConnected = false;	m_bSppConnected = false;	m_nComSpp = 0xFF;	m_hSppConn = BTSDK_INVALID_HANDLE;;	memset(m_DevAddr, 0, sizeof(m_DevAddr));}HandsFree::~HandsFree(){	Destroy();}bool HandsFree::Init(){	BTUINT32 ret;	Btsdk_AGAP_APPRegCbk(CallbackAgApEvent);	Btsdk_SCOInit((BTUINT8*)CallbackScoDataInd);	ret = Btsdk_AGAP_Init(BTSDK_AGAP_FEA_NREC | BTSDK_AGAP_FEA_VOICE_RECOG | BTSDK_AGAP_FEA_VOICETAG_PHONE_NUM | BTSDK_AGAP_FEA_REJ_CALL,						  BTSDK_AGAP_SCO_PKT_HV1 | BTSDK_AGAP_SCO_PKT_HV2 | BTSDK_AGAP_SCO_PKT_HV3, NULL);	if (ret != BTSDK_OK)	{		LOG(DEBUG, "AG init failed\n");		return false;	}	return true;}void HandsFree::Destroy(){	Btsdk_AGAP_Done();	Btsdk_SCODone();}bool HandsFree::ConnectAudioServer(){	if (strlen((char*)m_DevAddr) < 1)	{		IpcPacket o(HF_DISCONNECTED);		g_btSock.SendTo(o, BY_MAIN_PORT);		return false;	}	DisconnectAudioServer();	LOG(DEBUG, "HandsFree::ConnectAudioServer\n");	IpcPacket o(HF_SEARCHING);	g_btSock.SendTo(o, BY_MAIN_PORT);	BTUINT32 ret;	m_bAGConnected = false;	m_hDev = Btsdk_AddRemoteDevice(m_DevAddr);	if (m_hDev != BTSDK_INVALID_HANDLE)	{		ret = Btsdk_ConnectEx(m_hDev, BTSDK_CLS_HEADSET | BTSDK_CLS_HANDSFREE, 0, &m_hAGConn);		if (BTSDK_OK == ret)		{			LOG(DEBUG, "连接手柄成功 0x%08lx.\n", m_hAGConn);			m_bAGConnected = true;		}		else if (ret == BTSDK_ER_OPERATION_FAILURE)		{			LOG(DEBUG, "连接手柄失败 %lx\n", ret);			Btsdk_PrintErrorMessage(ret, BTSDK_TRUE);		}	}	else	{		LOG(DEBUG, "无效设备\n");	}	return m_bAGConnected;}void HandsFree::DisconnectAudioServer(){	if (m_hAGConn)	{		Btsdk_Disconnect(m_hAGConn);		m_hAGConn = BTSDK_INVALID_HANDLE;		m_nSpkVol = 0;		m_nAgState = AG_STATE_NULL;		m_hDev = BTSDK_INVALID_HANDLE;		m_bAGConnected = false;	}}void HandsFree::OnScoDataInd(BTUINT16 conn_hdl,BTUINT16 len,BTUINT8 *packet){	g_scoSock.Send2Pair((char*)packet, len);}void HandsFree::OnAGAPPEvCbk(BTUINT16 event, BTUINT8* param, BTUINT32 param_len){	char buf[128] = { 0 };	char extend_cmd[256] = { 0 };	switch (event)	{	case BTSDK_APP_EV_AGAP_STATE_CHANGED_IND:  // 状态改变		switch (*param)		{		case BTSDK_AGAP_ST_IDLE:			m_nAgState = AG_STATE_IDLE;			LOG(DEBUG, "连接前\n");			break;		case BTSDK_AGAP_ST_STANDBY:			m_nAgState = AG_STATE_STANDBY;			LOG(DEBUG, "连接后\n");			m_bAGConnected = true;			break;		case BTSDK_AGAP_ST_RINGING:			m_nAgState = AG_STATE_RINGING;			LOG(DEBUG, "AG 振铃\n");			break;		case BTSDK_AGAP_ST_OUTGOINGCALL:			m_nAgState = AG_STATE_OUTGOINGCALL;			LOG(DEBUG, "正在外拨\n");			break;		case BTSDK_AGAP_ST_ONGOINGCALL:			m_nAgState = AG_STATE_ONGOINGCALL;			LOG(DEBUG, "SCO 建立\n");			break;		case BTSDK_AGAP_ST_BVRA:			m_nAgState = AG_STATE_BVRA;			LOG(DEBUG, "Voice recognition\n");			break;		case BTSDK_AGAP_ST_VOVG:			m_nAgState = AG_STATE_VOVG;			LOG(DEBUG, "正在通话但没有 SCO 连接\n");			break;		default:			LOG(DEBUG, "未处理 BTSDK_APP_EV_AGAP_STATE_CHANGED_IND: %d\n", *param);			break;		}		break;	case BTSDK_APP_EV_AGAP_HF_AVAILABLE_IND:		{			LOG(DEBUG, "与手柄连接建立\n");			Btsdk_AGAP_ConnInfo *info = (Btsdk_AGAP_ConnInfo *)param;			LOG(DEBUG, "远端 %s 服务可用, %0x08lx\n", info->is_hsp ? "耳机" : "手柄", info->hdl);			if (!info->is_hsp)			{				// m_hRmtDev = info->hdl;				// Btsdk_GetConnectionProperty				LOG(DEBUG, "ConnectSPP\n");				ConnectSPP();				IpcPacket o(HF_CONNECTED);				g_btSock.SendTo(o, BY_MAIN_PORT);			}		}		break;	case BTSDK_APP_EV_AGAP_HF_UNAVAILABLE_IND: // 与手柄连接丢失		{		    // May be link lost! so, need to dispose link lost event accroding to            // the AG current state(ongoingcall etc.). (refer to CCAP 6.3.1)			m_nAgState = BTSDK_AGAP_ST_IDLE;			LOG(DEBUG, "与手柄连接丢失,重连 ...\n");			IpcPacket o(HF_DISCONNECTED);			g_btSock.SendTo(o, BY_MAIN_PORT);			// 重连			m_bAGConnected = false;			m_bSppConnected = false;			// RmtDevMgr::StartSearch();		}		break;	case BTSDK_APP_EV_AGAP_RMT_RELEASE_CALL_IND:		// The ongoing call is terminated by the remote party or due to network problem.		LOG(DEBUG, "对方挂机了\n");		Btsdk_AGAP_CancelCall();		break;	case BTSDK_APP_EV_AGAP_RMT_IS_BUSY_IND:		// HF should be able to hear busy tone if AG enables to transfer busy		// tone over audio connection		m_nAgState = AG_STATE_BUSYTONE;		break;	case BTSDK_APP_EV_AGAP_VOICE_RECOG_ACTIVATE_REQ:		// need to activate voice recognition		break;	case BTSDK_APP_EV_AGAP_VOICE_RECOG_DEACTIVATE_REQ:		// need to deactivate voice recognition		break;	case BTSDK_APP_EV_AGAP_INCOMINGCALL_ANSWERED_IND:		// need to answer the call if this event is initiated by HF		if (*param == BTSDK_AGAP_AG_ANSWERED_INCOMINGCALL)			LOG(DEBUG, "AG answered the incoming call!\n");		else if (*param == BTSDK_AGAP_HF_ANSWERED_INCOMINGCALL)		{			LOG(DEBUG, "手柄接听来电\n");			IpcPacket o(VOIP_ANSWERCALL);			g_btSock.SendTo(o, VOIP_PORT);		}        break;	case BTSDK_APP_EV_AGAP_CALL_CANCELED_IND:		{			// need to cancel the call if this event is initiated by HF			if (*param == BTSDK_AGAP_AG_CANCELED_CALL)				LOG(DEBUG, "通话取消原因: Audio Gateway 取消通话\n");			else if (*param == BTSDK_AGAP_HF_CANCELED_CALL)			{				LOG(DEBUG, "通话取消原因: 手柄挂机\n");				IpcPacket o(VOIP_HANGUP);				g_btSock.SendTo(o, VOIP_PORT);			}			else if (*param == BTSDK_AGAP_NETWORK_CANCELED_CALL)				LOG(DEBUG, "通话取消原因: Network event received!\n");			else if (*param == BTSDK_AGAP_TBUSY_CANCELED_CALL)				LOG(DEBUG, "通话取消原因: Tbusy timeout!\n");			// IpcPacket o(VOIP_HANGUP);			// btSock.SendTo(o, VOIP_PORT);		}		break;	case BTSDK_APP_EV_AGAP_AUDIO_CONN_ESTABLISHED_IND:		// need to do something here.        LOG(DEBUG, "SCO 连接建立\n");		break;	case BTSDK_APP_EV_AGAP_AUDIO_CONN_RELEASED_IND:		// need to do something here.		LOG(DEBUG, "SCO 连接释放\n");		break;	case BTSDK_APP_EV_AGAP_HF_DIAL_IND: // 手柄外拨号码		// need to place a call with the phone number supplied by the HF		// device here. if param == NULL then this event means HS originate		// outgoing call (may be last number redial or voice recognition.)		if (!param)			LOG(DEBUG, "耳机外拨\n");		else		{		    LOG(DEBUG, "手柄外拨 ");		    if (param_len <= 30)			{			    memcpy(buf, param, param_len);			    buf[param_len] = 0;			    LOG(DEBUG, "%s\n", buf);				Btsdk_AGAP_OriginateCall();				IpcPacket o(VOIP_MAKECALL);				o.WriteString(buf);				g_btSock.SendTo(o, VOIP_PORT);			}			else			{                LOG(DEBUG, "The phone number is too long\n");			}		}		break;	case BTSDK_APP_EV_AGAP_HF_MEM_DIAL_IND:		// need to memory dialing here.		LOG(DEBUG, "手柄外拨电话本 ");		if (param_len <= 30)		{			memcpy(buf, param, param_len);			buf[param_len] = 0;			LOG(DEBUG, "%s\n", buf);		}		else            LOG(DEBUG, "The memory location is too long\n");		break;	case BTSDK_APP_EV_AGAP_HF_LASTNUM_REDIAL_IND:		{			// need to redial the last dialed phone number here.			LOG(DEBUG, "重拨\n");			Btsdk_AGAP_OriginateCall();			IpcPacket o(VOIP_MAKECALL);			o.WriteString(buf);			g_btSock.SendTo(o, VOIP_PORT);		}		break;	case BTSDK_APP_EV_AGAP_CUR_INDICATOR_VAL_REQ:        // need to call this function depending on the current state of AG        // (standby, ongoing call, outgoing call or incoming call; service        // available or service unavailable).        Btsdk_AGAP_SetCurIndicatorVal(BTSDK_AGAP_INDICATOR_SVC_AVAILABLE);  // call: 0; callsetup: 0; service: 1		break;	case BTSDK_APP_EV_AGAP_DTMF_IND:		// need to transmit the received DTMF code.		LOG(DEBUG, "收到 DTMF 码 %c\n", *param);		break;	case BTSDK_APP_EV_AGAP_SPKVOL_CHANGED_IND:		// need to record the speaker volume level of HF device, maybe it is		// needed to change speaker volume of the AG		LOG(DEBUG, "手柄调整音量 from %d to %d\n", m_nSpkVol, *param);		m_nSpkVol = *param;		break;	case BTSDK_APP_EV_AGAP_VOICETAG_PHONE_NUM_REQ:        // need to indicate user to input phone number for the voice-tag at        // the HF device side, and it is allowed to input 32 digits at most.        LOG(DEBUG, "\nInput Phone number:123456789\n\n");		// fix me		// Btsdk_AGAP_VoiceTagPhoneNumRsp("\"123456789\"", 11);		break;	case BTSDK_APP_EV_AGAP_NREC_DISENABLE_IND:        LOG(DEBUG, "need to disable NREC here.\n");		break;	case BTSDK_APP_EV_AGAP_GENERATE_INBAND_RINGTONE_IND:		LOG(DEBUG, "产生振铃声\n");		// need to generate in-band ring tone here.		break;	case BTSDK_APP_EV_AGAP_TERMINATE_INBAND_RINGTONE_IND:		LOG(DEBUG, "停止振铃声\n");   	    // need to terminate its in-band ring tone here!		break;	case BTSDK_APP_EV_AGAP_NETWORK_AVAILABLE_IND:		LOG(DEBUG, "Cellular network service is available!\n");		break;	case BTSDK_APP_EV_AGAP_NETWORK_UNAVAILABLE_IND:	    // HF should be able to hear busy tone if AG enables to transfer busy	    // tone over audio connection when in OngoingCall or OutgoingCall	    // state. (refer to CCAP 6.3.2; 6.3.3; 6.3.4)		LOG(DEBUG, "Cellular network service is unavailable!\n");		break;	case BTSDK_APP_EV_AGAP_EXTEND_CMD_IND:		// need to deal with the extended AT Command here.	    memcpy(extend_cmd, param, param_len);	    extend_cmd[param_len] = 0;	    LOG(DEBUG, "Extended ATCommand: %s\n", extend_cmd);	    // Btsdk_AGAP_ExtendCmd("\r\nERROR\r\n");		break;	default:		LOG(DEBUG, "未处理 OnAGAPPEvCbk 事件: %d\n", event);		break;	}}bool HandsFree::ConnectSPP(){	DisconnectSpp();	BtSdkConnectionPropertyStru conn_prop;	BtSdkSPPConnParamStru comstru;	comstru.size = sizeof(BtSdkSPPConnParamStru);	comstru.mask = 0;	comstru.com_index = 7;	BTINT32 result = Btsdk_StartClientEx(m_hDev, BTSDK_CLS_SERIAL_PORT, 0, &m_hSppConn);	Btsdk_GetConnectionProperty(m_hSppConn, &conn_prop);	bool b;    if (result == BTSDK_OK)    {		LOG(DEBUG, "连接 SPP 服务成功\n");		m_nComSpp = Btsdk_GetClientPort(m_hSppConn);  /* get com number */		m_bSppConnected = true;		b = true;	}	else if (result == BTSDK_ER_CONNECTION_EXIST)	{		LOG(DEBUG, "连接已存在\n");		b = true;	}    else	{		LOG(DEBUG, "SPP 连接失败 %lu\n", result);        b = false;    }	return b;}void HandsFree::DisconnectSpp(){	if (m_hSppConn != BTSDK_INVALID_HANDLE)	{		BTINT32 result = Btsdk_Disconnect(m_hSppConn);		if (result == BTSDK_OK)		{			LOG(DEBUG, "断开 SPP 连接成功\n");			m_nComSpp = 0xFF;		}		else		{			LOG(DEBUG, "断开 SPP 连接失败\n");		}	}	m_bSppConnected = false;}void HandsFree::OnSPPDataInd(BTUINT16 com, BTUINT8 *data, BTUINT32 len){	static int len_spprecv = 0;	static unsigned char spp_recv[4 * 1024] = { 0 };	int i;	// LOG(DEBUG, "################\n");	// for (i = 0; i < len; i++)	// {	// 	LOG(DEBUG, "%02x ", *(data + i));	// }	// LOG(DEBUG, "\n\n");	// return;	memcpy(spp_recv + len_spprecv, (char*)data, len);	len_spprecv += len;	LOG(DEBUG, "################\n");	for (i = 0; i < len_spprecv; i++)	{		LOG(DEBUG, "%02x ", *(spp_recv + i));	}	LOG(DEBUG, "\n\n");	while (1)	{		if ((len_spprecv >= 4) && (spp_recv[0] == 0x88) && (spp_recv[1] == 0x7e))		{			unsigned short framlength = spp_recv[2];			framlength = framlength << 8;			unsigned short temp = spp_recv[3];			framlength = framlength | temp;			LOG(DEBUG, "frame len: %d\n", framlength);			if (len_spprecv == framlength) // one frame only			{				LOG(DEBUG, "one frame only\n");				g_btSock.OnRecvSpp(com, (char*)spp_recv, framlength);				len_spprecv = 0;				memset(spp_recv, 0, sizeof(spp_recv));				break;			}			else if (len_spprecv > framlength) // more than one frame			{				LOG(DEBUG, "more than one frame\n");				g_btSock.OnRecvSpp(com, (char*)spp_recv, framlength);				for (i = 0; i < (len_spprecv - framlength); i++)					spp_recv[i] = spp_recv[framlength + i];				for (i = len_spprecv - framlength; i < (int)sizeof(spp_recv); i++)					spp_recv[i] = 0;				len_spprecv -= framlength;			}			else			{				LOG(DEBUG, "NOT a complete frame %d, wait ...\n", len_spprecv);				break;			}		}		else		{			// 丢弃不合的数据			LOG(DEBUG, "not a frame len_spprecv=%d\n", len_spprecv);			for (i = 0; i < len_spprecv; i++)				LOG(DEBUG, "%02x ", *(spp_recv + i));			LOG(DEBUG, "\n");			int n = 0;			for (i = 0; i < len_spprecv; i++)			{				if (*(spp_recv + i) == 0 && i + 1 < len_spprecv && *(spp_recv + i + 1) != 0x88)				{					n++;				}				else if (*(spp_recv + i) == 0 && i + 1 < len_spprecv && *(spp_recv + i + 1) == 0x88)				{					n++;					break;				}			}			LOG(DEBUG, "---------- %d\n", n);			if (n > 0)			{				for (i = 0; i < (len_spprecv - n); i++)					spp_recv[i] = spp_recv[n + i];				for (i = len_spprecv - n; i < (int)sizeof(spp_recv); i++)					spp_recv[i] = 0;				len_spprecv -= n;				LOG(DEBUG, "++++++++++++ after strip\n");				for (i = 0; i < len_spprecv; i++)					LOG(DEBUG, "%02x ", *(spp_recv + i));				LOG(DEBUG, "\n");			}			break;		}	}}void HandsFree::SendSppData(const char* data, int len){	if (!m_bSppConnected)	{		IpcPacket o(BT_SPP_NOT_CONNECTED);		g_btSock.SendTo(o, BY_MAIN_PORT);	}	RcvSdrvData(m_nComSpp, (char*)data, len);	LOG(DEBUG, "**** Send Spp %d\n", len);	for (int i = 0; i < len; i++)		LOG(DEBUG, "%02x ", (unsigned char)*(data + i));	LOG(DEBUG, "\n");}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -