📄 bthandsfree.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 + -