📄 handler.cpp
字号:
m_AGProps.fNotifyCallWait = FALSE;
}
fSendOk = TRUE;
break;
}
pszParams++;
}
if (fSendOk) {
SendATCommand(AT_OK, sizeof(AT_OK)-1);
}
else {
SendATCommand(AT_ERROR, sizeof(AT_ERROR)-1);
}
Unlock();
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: --AGEngine::OnEnableCallWaiting\n"));
}
// This method is called by the peer to enable "call line identification".
void CAGEngine::OnEnableCLI(LPSTR pszParams, int cchParam)
{
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Calling AGEngine::OnEnableCLI\n"));
BOOL fSendOk = FALSE;
Lock();
ASSERT(m_AGProps.state >= AG_STATE_CONNECTING);
while (*pszParams != '\0') {
if (*pszParams != ' ') {
if (*pszParams == '1') {
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Enabling CLI.\n"));
m_AGProps.fNotifyCLI = TRUE;
}
else {
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Disabling CLI.\n"));
m_AGProps.fNotifyCLI = FALSE;
}
fSendOk = TRUE;
break;
}
pszParams++;
}
if (fSendOk) {
SendATCommand(AT_OK, sizeof(AT_OK)-1);
}
else {
SendATCommand(AT_ERROR, sizeof(AT_ERROR)-1);
}
Unlock();
}
// This method is called when the parser receives an unknown command
void CAGEngine::OnUnknownCommand(void)
{
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Calling AGEngine::OnUnknownCommand\n"));
Lock();
ASSERT(m_AGProps.state >= AG_STATE_CONNECTING);
if (m_AGProps.state >= AG_STATE_CONNECTING) {
SendATCommand(AT_ERROR, sizeof(AT_ERROR)-1);
}
Unlock();
}
// This method is called when the peer device responds with OK
void CAGEngine::OnOK(void)
{
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Got OK response from peer.\n"));
}
// This method is called when the peer devices responds with ERROR
void CAGEngine::OnError(void)
{
DEBUGMSG(ZONE_WARN, (L"BTAGSVC: Got ERROR response from peer.\n"));
}
// This method is called when service goes up or down
void CAGEngine::OnServiceCallback(BOOL fHaveService)
{
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: OnServiceCallback: %d\n", fHaveService));
if (m_AGProps.fHaveService != fHaveService) {
Lock();
m_AGProps.fHaveService = fHaveService;
if (m_AGProps.fIndicatorUpdates) {
CHAR szCommand[MAX_SEND_BUF];
int cbCommand = _snprintf(szCommand, MAX_SEND_BUF-1, "\r\n+CIEV:1,%d\r\n", (fHaveService?1:0));
szCommand[MAX_SEND_BUF-1]='\0';
if (cbCommand > 0) {
SendATCommand(szCommand, cbCommand);
}
}
Unlock();
}
}
// This method is called by the Network when an event has occured
void CAGEngine::OnNetworkEvent(DWORD dwEvent, LPVOID lpvParam, DWORD cbParam)
{
switch (dwEvent) {
case NETWORK_EVENT_CALL_IN:
OnNetworkCallIn((LPSTR)lpvParam);
break;
case NETWORK_EVENT_CALL_OUT:
OnNetworkCallOut();
break;
case NETWORK_EVENT_CALL_CONNECT:
OnNetworkAnswerCall();
break;
case NETWORK_EVENT_CALL_BUSY:
case NETWORK_EVENT_CALL_DISCONNECT:
if (sizeof(DWORD) > cbParam) {
DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Received error event from network component with invalid param size.\n"));
ASSERT(0);
}
else {
OnNetworkHangupCall((DWORD)lpvParam, (NETWORK_EVENT_CALL_BUSY == dwEvent) ? HANGUP_DELAY_BUSY_MS : HANGUP_DELAY_MS);
}
break;
case NETWORK_EVENT_CALL_REJECT:
OnNetworkRejectCall();
break;
case NETWORK_EVENT_RING:
OnNetworkRing();
break;
case NETWORK_EVENT_CALL_INFO:
OnNetworkInfo((LPSTR)lpvParam);
break;
case NETWORK_EVENT_FAILED:
if (sizeof(NetworkCallFailedInfo) > cbParam) {
DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Received error event from network component with invalid param size.\n"));
ASSERT(0);
}
else {
OnNetworkCallFailed(((NetworkCallFailedInfo*)lpvParam)->usCallType, ((NetworkCallFailedInfo*)lpvParam)->dwStatus);
}
break;
default:
DEBUGMSG(ZONE_WARN, (L"BTAGSVC: Unknown network event: %d\n", dwEvent));
ASSERT(0);
}
}
// This method is called by the Network when a call is answered
void CAGEngine::OnNetworkAnswerCall(void)
{
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Calling AGEngine::OnNetworkAnswerCall\n"));
Lock();
if ((m_AGProps.state >= AG_STATE_CONNECTED) && m_AGProps.fIndicatorUpdates) {
SendATCommand("\r\n+CIEV:2,1\r\n", 13); // Call is active
SendATCommand("\r\n+CIEV:3,0\r\n", 13); // Call Setup is completed
}
m_AGProps.usCallSetup = 0;
m_AGProps.fInCall = TRUE;
if ((m_AGProps.state >= AG_STATE_CONNECTED) && m_AGProps.fUseHFAudio) {
if (m_AGProps.usCallType == AG_CALL_TYPE_IN) {
DWORD dwErr = OpenAudioChannel();
if ((ERROR_SUCCESS != dwErr) && (ERROR_ALREADY_INITIALIZED != dwErr)) {
DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Error opening audio connection: %d\n", dwErr));
}
}
}
else if (m_AGProps.fPowerSave || !m_AGProps.fHandsfree) {
// Call was answered in the handset close connection in power-save mode
CloseControlChannel();
}
m_AGProps.fUseHFAudio = FALSE;
Unlock();
}
// This method is called by the Network when a call is disconnected (or busy)
void CAGEngine::OnNetworkHangupCall(DWORD dwRemainingConnections, DWORD dwHangUpDelayMS)
{
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Calling AGEngine::OnNetworkHangupCall\n"));
Lock();
if (dwRemainingConnections == 0) {
if (m_AGProps.state >= AG_STATE_CONNECTED) {
if (m_AGProps.fIndicatorUpdates && m_AGProps.fInCall) {
// For hangup call, send call indicator as inactive
SendATCommand("\r\n+CIEV:2,0\r\n", 13);
}
else if (m_AGProps.fIndicatorUpdates) {
// For rejected call, send callsetup indicator as inactive
SendATCommand("\r\n+CIEV:3,0\r\n", 13);
}
wcscpy(m_wszCLI, L"");
m_fCancelCloseConnection = FALSE;
m_CloseCookie = m_pTP->ScheduleEvent(TimeoutConnection, (LPVOID)this, HANGUP_DELAY_MS);
}
m_AGProps.usCallSetup = 0;
m_AGProps.fInCall = FALSE;
}
else {
DWORD dwState = 0;
DWORD dwErr = BthAGNetworkGetCallState(&dwState);
// We have a call connected, if it is not active or on hold,
// we need to do some clean up
if ((ERROR_SUCCESS == dwErr) &&
!(dwState & NETWORK_FLAGS_STATE_HOLD) &&
!(dwState & NETWORK_FLAGS_STATE_ACTIVE)) {
if (m_AGProps.fIndicatorUpdates && m_AGProps.fInCall) {
// For hangup call, send call indicator as inactive
SendATCommand("\r\n+CIEV:2,0\r\n", 13);
}
wcscpy(m_wszCLI, L"");
m_AGProps.fInCall = FALSE;
}
}
Unlock();
}
// This method is called by the Network when a call is rejected
void CAGEngine::OnNetworkRejectCall(void)
{
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Calling AGEngine::OnNetworkRejectCall\n"));
Lock();
m_AGProps.usCallSetup = 0;
m_AGProps.fInCall = FALSE;
if (m_AGProps.state >= AG_STATE_CONNECTED) {
if (m_AGProps.fIndicatorUpdates) {
SendATCommand("\r\n+CIEV:3,0\r\n", 13); // Call Setup is complete
}
wcscpy(m_wszCLI, L"");
CloseAudioChannel();
if (m_AGProps.fPowerSave || !m_AGProps.fHandsfree) {
CloseControlChannel();
}
}
Unlock();
}
// This method is called by the Network when an incoming call is placed
void CAGEngine::OnNetworkCallIn(LPSTR pszNumber)
{
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Calling AGEngine::OnNetworkCallIn\n"));
Lock();
if (m_AGProps.fInCall) {
// Already in a call, send call-wait signal but do not accept call.
if (m_AGProps.fNotifyCallWait) {
CHAR szCommand[MAX_SEND_BUF];
int cbCommand;
if (pszNumber[0] == 0) {
cbCommand = _snprintf(szCommand, MAX_SEND_BUF-1, "\r\n+CCWA:\"0\",0,1\r\n");
}
else {
cbCommand = _snprintf(szCommand, MAX_SEND_BUF-1, "\r\n+CCWA:\"%s\",0,1\r\n", pszNumber);
}
szCommand[MAX_SEND_BUF-1]='\0';
if (cbCommand > 0) {
SendATCommand(szCommand, cbCommand);
}
SendATCommand("\r\n+CIEV:3,1\r\n", 13);
}
}
else {
m_AGProps.usCallType = AG_CALL_TYPE_IN;
m_AGProps.fMuteRings = FALSE;
DWORD dwErr = OpenControlChannel(FALSE);
if ((ERROR_SUCCESS != dwErr) && (ERROR_ALREADY_INITIALIZED != dwErr)) {
DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Error opening AG Connection: %d.\n", dwErr));
}
else {
if (! m_hUIThread) {
m_hUIThread = CreateThread(NULL, 0, AGUIThread, this, 0, NULL);
}
if (m_hUIThread) {
if (m_AGProps.fHandsfree) {
if (m_AGProps.usHFCapability & AG_CAP_INBAND_RING) {
if (m_AGProps.state >= AG_STATE_AUDIO_UP) {
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Incoming call is using in-band ring tone.\n"));
SendATCommand("\r\n+BSIR:1\r\n", 11); // In-band ring tone on
}
else if (m_AGProps.state >= AG_STATE_CONNECTED) {
SendATCommand("\r\n+BSIR:0\r\n", 11); // In-band ring tone off
}
}
if (m_AGProps.fIndicatorUpdates) {
SendATCommand("\r\n+CIEV:3,1\r\n", 13); // Call Setup is ongoing
}
m_AGProps.usCallSetup = 1;
if (pszNumber[0] != 0) {
WCHAR wszNumber[MAX_PHONE_NUMBER];
ASSERT(ARRAY_SIZE(wszNumber) == ARRAY_SIZE(m_wszCLI));
if (0 < MultiByteToWideChar(CP_ACP, 0, pszNumber, -1, wszNumber, ARRAY_SIZE(wszNumber))) {
if (m_AGProps.fNotifyCLI) {
if (FALSE == BthAGGetNameByPhoneNumber(pszNumber, m_wszCLI)) {
wcscpy(m_wszCLI, wszNumber);
}
}
else {
wcscpy(m_wszCLI, wszNumber);
}
}
else {
ASSERT(0);
}
}
}
}
else {
DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Out of resources.\n"));
}
}
}
Unlock();
}
// This method is called by the Network when an outgoing call is placed
void CAGEngine::OnNetworkCallOut(void)
{
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Calling AGEngine::OnNetworkCallOut\n"));
Lock();
m_AGProps.usCallType = AG_CALL_TYPE_OUT;
m_AGProps.fUseHFAudio = TRUE; // By default outgoing calls will connect HF audio
m_fAudioConnect = TRUE;
DWORD dwErr = OpenControlChannel(FALSE);
if ((ERROR_SUCCESS != dwErr) && (ERROR_ALREADY_INITIALIZED != dwErr)) {
DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Error opened AG Connection: %d.\n", dwErr));
}
else {
if (! m_hUIThread) {
m_hUIThread = CreateThread(NULL, 0, AGUIThread, this, 0, NULL);
}
if (m_hUIThread) {
if (m_AGProps.fHandsfree) {
if (m_AGProps.fIndicatorUpdates) {
SendATCommand("\r\n+CIEV:3,3\r\n", 13); // Call Setup is alerting remote party
}
m_AGProps.usCallSetup = 3;
}
}
else {
DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Out of resources.\n"));
}
}
Unlock();
}
// This method is called by the Network when a caller id notification is delayed
void CAGEngine::OnNetworkInfo(LPSTR pszNumber)
{
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Calling AGEngine::OnNetworkInfo number:%hs\n", pszNumber));
Lock();
if (pszNumber[0] != 0) {
WCHAR wszNumber[MAX_PHONE_NUMBER];
ASSERT(ARRAY_SIZE(wszNumber) == ARRAY_SIZE(m_wszCLI));
if (0 < MultiByteToWideChar(CP_ACP, 0, pszNumber, -1, wszNumber, ARRAY_SIZE(wszNumber))) {
if (m_AGProps.fNotifyCLI) {
if (FALSE == BthAGGetNameByPhoneNumber(pszNumber, m_wszCLI)) {
wcscpy(m_wszCLI, wszNumber);
}
}
else {
wcscpy(m_wszCLI, wszNumber);
}
}
else {
ASSERT(0);
}
}
Unlock();
}
// This method is called by the Network when a RING is received
void CAGEngine::OnNetworkRing(void)
{
DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Calling AGEngine::OnNetworkRing\n"));
Lock();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -