📄 handler.cpp
字号:
m_AGProps.fUseHFAudio = TRUE; // Indicate call is answered from HF
AddRef();
Unlock();
DWORD dwErr = BthAGNetworkAnswerCall();
Lock();
DelRef();
if (ERROR_SUCCESS == dwErr) {
SendATCommand(AT_OK, sizeof(AT_OK)-1);
}
else {
DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Error answering call: %d\n", dwErr));
SendATCommand(AT_ERROR, sizeof(AT_ERROR)-1);
m_AGProps.fUseHFAudio = FALSE;
}
}
else {
SendATCommand(AT_ERROR, sizeof(AT_ERROR)-1);
}
Unlock();
}
// This method is called by the peer device to hang-up or reject an incoming call
void CAGEngine::OnHangupCall(LPSTR pszParam, int cchParam)
{
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Calling AGEngine::OnHangupCall\n"));
Lock();
if (((m_AGProps.state == AG_STATE_RINGING) ||
(m_AGProps.state == AG_STATE_RINGING_AUDIO_UP)) &&
(!(m_AGProps.usHFCapability & AG_CAP_REJECT_CALL)))
{
// Do not support rejecting incoming calls
SendATCommand(AT_ERROR, sizeof(AT_ERROR)-1);
}
else {
AddRef();
Unlock();
DWORD dwErr = BthAGNetworkDropCall(NETWORK_FLAGS_DROP_ACTIVE);
Lock();
DelRef();
if (ERROR_SUCCESS == dwErr) {
SendATCommand(AT_OK, sizeof(AT_OK)-1);
}
else {
DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Error dropping call: %d\n", dwErr));
SendATCommand(AT_ERROR, sizeof(AT_ERROR)-1);
}
}
Unlock();
}
// This method is called by the peer to transmit DTMF codes
void CAGEngine::OnDTMF(LPSTR pszParams, int cchParam)
{
WCHAR wszDTMF[MAX_SEND_BUF];
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Calling AGEngine::OnDTMF\n"));
Lock();
ASSERT(m_AGProps.state >= AG_STATE_CONNECTED);
if (m_AGProps.fInCall) {
SendATCommand(AT_OK, sizeof(AT_OK)-1);
AddRef();
Unlock();
if (0 < MultiByteToWideChar(CP_ACP, 0, pszParams, -1, wszDTMF, ARRAY_SIZE(wszDTMF))) {
BthAGNetworkTransmitDTMF(wszDTMF);
}
else {
ASSERT(0);
}
Lock();
DelRef();
}
else {
SendATCommand(AT_ERROR, sizeof(AT_ERROR)-1);
}
Unlock();
}
// This method is called by the peer to place a call on hold or enable
// a multi-party call.
void CAGEngine::OnCallHold(LPSTR pszParams, int cchParam)
{
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Calling AGEngine::OnCallHold\n"));
Lock();
ASSERT(m_AGProps.state >= AG_STATE_CONNECTED);
DWORD dwErr;
BOOL fSuccess = FALSE;
BOOL fServiceConnectionUp = FALSE;
BOOL fCallSetup = FALSE;
if (m_AGProps.usHFCapability & AG_CAP_3WAY_CALL) {
if (cchParam < 1) {
// Bad parameters, do nothing to send error
}
else if (pszParams[0] == '?') {
// Test command for supported call-waiting features
SendATCommand("\r\n+CHLD:(0,1,2)\r\n", 17);
SendATCommand(AT_OK, sizeof(AT_OK)-1);
fServiceConnectionUp = TRUE;
fSuccess = TRUE;
}
else if (pszParams[0] == '0') {
// Release all calls
AddRef();
Unlock();
dwErr = BthAGNetworkDropCall(NETWORK_FLAGS_DROP_ALL);
Lock();
DelRef();
if (ERROR_SUCCESS == dwErr) {
fSuccess = TRUE;
SendATCommand(AT_OK, sizeof(AT_OK)-1);
}
}
else if (pszParams[0] == '1') {
// Release active calls, transfer held calls
m_AGProps.fUseHFAudio = TRUE;
AddRef();
Unlock();
dwErr = BthAGNetworkDropCall(NETWORK_FLAGS_DROP_ACTIVE);
Lock();
DelRef();
if (ERROR_SUCCESS == dwErr) {
m_AGProps.fUseHFAudio = TRUE;
AddRef();
Unlock();
dwErr = BthAGNetworkUnholdCall();
Lock();
DelRef();
if (ERROR_SUCCESS == dwErr) {
fSuccess = TRUE;
SendATCommand(AT_OK, sizeof(AT_OK)-1);
}
}
}
else if (pszParams[0] == '2') {
// Swap calls
m_AGProps.fUseHFAudio = TRUE;
AddRef();
Unlock();
dwErr = BthAGNetworkSwapCall();
Lock();
DelRef();
if (ERROR_SUCCESS == dwErr) {
fSuccess = TRUE;
SendATCommand(AT_OK, sizeof(AT_OK)-1);
}
}
else if ((pszParams[0] == '3') || (pszParams[0] == '4')) {
// We don't support these parameters, do nothing to send error
}
}
if (! fSuccess) {
SendATCommand(AT_ERROR, sizeof(AT_ERROR)-1);
m_AGProps.fUseHFAudio = TRUE;
}
if (fServiceConnectionUp) {
ServiceConnectionUp();
}
Unlock();
}
PFN_BthAGOnVoiceTag CAGEngine::GetVoiceTagHandler()
{
return m_pParser ? m_pParser->GetVoiceTagHandler() : NULL;
}
// This method is called by the peer to start voice recognition
void CAGEngine::OnVoiceRecognition(LPSTR pszParams, int cchParam)
{
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Calling AGEngine::OnVoiceRecognition\n"));
Lock();
ASSERT(m_AGProps.state >= AG_STATE_CONNECTED);
if (m_AGProps.usHFCapability & AG_CAP_VOICE_RECOG) {
if (cchParam != 1) {
SendATCommand(AT_ERROR, sizeof(AT_ERROR)-1);
}
else if (pszParams[0] == '0') {
SendATCommand(AT_OK, sizeof(AT_OK)-1);
AddRef();
Unlock();
BthAGPhoneExtEvent(AG_PHONE_EVENT_VOICE_RECOG, 0, (void*)GetVoiceTagHandler());
Lock();
DelRef();
}
else if (pszParams[0] == '1') {
SendATCommand(AT_OK, sizeof(AT_OK)-1);
DWORD dwErr = OpenAudioChannel();
if ((ERROR_SUCCESS != dwErr) && (ERROR_ALREADY_INITIALIZED != dwErr)) {
DEBUGMSG(ZONE_WARN, (L"BTAGSVC: Call to open audio channel failed. Can't do voice recognition.\n"));
}
AddRef();
Unlock();
BthAGPhoneExtEvent(AG_PHONE_EVENT_VOICE_RECOG, 1, (void*)GetVoiceTagHandler());
Lock();
DelRef();
}
}
else {
SendATCommand(AT_ERROR, sizeof(AT_ERROR)-1);
}
Unlock();
}
// This method is called by the peer to query supported features of the AG
void CAGEngine::OnSupportedFeatures(LPSTR pszParams, int cchParam)
{
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Calling AGEngine::OnSupportedFeatures\n"));
Lock();
ASSERT(m_AGProps.state >= AG_STATE_CONNECTING);
LPSTR pTmp;
m_AGProps.usRemoteFeatures = (USHORT) strtol(pszParams, &pTmp, 10);
if (pTmp != (pszParams + strlen(pszParams))) {
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: AT+BRSF Command was poorly formatted.\n"));
SendATCommand(AT_ERROR, sizeof(AT_ERROR)-1);
}
else {
CHAR pszCommand[MAX_SEND_BUF];
m_AGProps.fHandsfree = TRUE;
int cchCommand = _snprintf(pszCommand, MAX_SEND_BUF-1, "\r\n+BRSF:%d\r\n", m_AGProps.usHFCapability);
pszCommand[MAX_SEND_BUF-1]='\0';
if (cchCommand > 0) {
SendATCommand(pszCommand, cchCommand);
SendATCommand(AT_OK, sizeof(AT_OK)-1);
}
else {
SendATCommand(AT_ERROR, sizeof(AT_ERROR)-1);
}
}
Unlock();
}
// This method is called by the peer to get a list of supported indicators
void CAGEngine::OnTestIndicators(LPSTR pszParams, int cchParam)
{
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Calling AGEngine::OnTestIndicators\n"));
CHAR pszCommand[MAX_SEND_BUF];
Lock();
ASSERT(m_AGProps.state >= AG_STATE_CONNECTING);
m_AGProps.fHandsfree = TRUE;
int cchCommand = _snprintf(pszCommand, MAX_SEND_BUF-1, "\r\n+CIND: (\"service\",(0,1)),(\"call\",(0,1)),(\"callsetup\",(0-3))\r\n");
pszCommand[MAX_SEND_BUF-1]='\0';
if (cchCommand > 0) {
SendATCommand(pszCommand, cchCommand);
SendATCommand(AT_OK, sizeof(AT_OK)-1);
}
else {
SendATCommand(AT_ERROR, sizeof(AT_ERROR)-1);
}
Unlock();
}
// This method is called by the peer to read the supported indicators
void CAGEngine::OnReadIndicators(LPSTR pszParams, int cchParam)
{
CHAR pszCommand[MAX_SEND_BUF];
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Calling AGEngine::OnReadIndicators\n"));
Lock();
ASSERT(m_AGProps.state >= AG_STATE_CONNECTING);
m_AGProps.fHandsfree = TRUE;
BOOL fService = (m_AGProps.fHaveService?1:0);
BOOL fCall = ((m_AGProps.fInCall)?1:0);
// Send status of all indicators
int cchCommand = _snprintf(pszCommand, MAX_SEND_BUF-1, "\r\n+CIND: %d,%d,%d\r\n", fService, fCall, m_AGProps.usCallSetup);
pszCommand[MAX_SEND_BUF-1]='\0';
if (cchCommand > 0) {
SendATCommand(pszCommand, cchCommand);
SendATCommand(AT_OK, sizeof(AT_OK)-1);
}
else {
SendATCommand(AT_ERROR, sizeof(AT_ERROR)-1);
}
Unlock();
}
// This method is called by the peer to register for indicator updates.
void CAGEngine::OnRegisterIndicatorUpdates(LPSTR pszParams, int cchParam)
{
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Calling AGEngine::OnRegisterIndicatorUpdates\n"));
//
// Format of the string we are parsing: "a,b,c,d\n".
// We care about a and d.
//
Lock();
ASSERT(m_AGProps.state >= AG_STATE_CONNECTING);
DWORD cParam = 0;
BOOL fSendOk = FALSE;
while (*pszParams != '\0') {
if (*pszParams == ',') {
cParam++;
}
else if (cParam == 0 && (*pszParams != ' ')) {
// If first param is not 3 we don't care about this command
if (*pszParams != '3') {
break;
}
}
else if ((cParam == 3) && (*pszParams != ' ')) {
// Fourth param is indicator update flag
if (*pszParams == '1') {
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Enabling Indicator Updates.\n"));
m_AGProps.fIndicatorUpdates = TRUE;
}
else {
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Disabling Indicator Updates.\n"));
m_AGProps.fIndicatorUpdates = FALSE;
}
m_AGProps.fHandsfree = TRUE;
fSendOk = TRUE;
break;
}
pszParams++;
}
if (fSendOk) {
SendATCommand(AT_OK, sizeof(AT_OK)-1);
}
else {
SendATCommand(AT_ERROR, sizeof(AT_ERROR)-1);
}
if ((m_AGProps.usHFCapability & AG_CAP_3WAY_CALL) &&
(m_AGProps.usRemoteFeatures & HF_CAP_3WAY_CALL)) {
// If we mutually support 3-way call, service level connection
// is not up until after AT+CHLD=?
}
else {
ServiceConnectionUp();
}
Unlock();
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: --AGEngine::OnRegisterIndicatorUpdates\n"));
}
// This method is called by the peer to enable call-waiting
void CAGEngine::OnEnableCallWaiting(LPSTR pszParams, int cchParam)
{
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Calling AGEngine::OnEnableCallWaiting\n"));
Lock();
ASSERT(m_AGProps.state >= AG_STATE_CONNECTING);
BOOL fSendOk = FALSE;
while (*pszParams != '\0') {
if (*pszParams != ' ') {
if (*pszParams == '1') {
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Enabling Call Waiting.\n"));
m_AGProps.fNotifyCallWait = TRUE;
}
else {
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Disabling Call Waiting.\n"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -