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

📄 tapi.cpp

📁 Windows CE操作系统中适用的蓝牙驱动程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
            
            BthAGOnNetworkEvent(NETWORK_EVENT_FAILED, (LPVOID)&CallFailInfo, sizeof(CallFailInfo));
            
            TapiLock();
        }

        DeleteTapiCall(pMsg->dwParam1);
    }
}


//
// This function is called when a TAPI call state changes
//
void TapiEventCallStateChange(LPLINEMESSAGE pMsg)
{
    HCALL hCall = (HCALL) pMsg->hDevice;

    if (ERROR_SUCCESS != GetCallInfo(hCall)) {
        DEBUGMSG(ZONE_WARN, (L"BTAGSVC: Query for caller id failed.\n"));
        goto exit;
    }

    // Make sure is of the correct media mode
    if (LINEMEDIAMODE_INTERACTIVEVOICE != g_Data.pCallInfo->dwMediaMode) {
        DEBUGMSG(ZONE_WARN, (L"BTAGSVC: Call is of wrong media mode: 0x%X\n", g_Data.pCallInfo->dwMediaMode));
        goto exit;

    }            
                
    if (LINECALLSTATE_DISCONNECTED == pMsg->dwParam1) {
        if ((g_Data.hCall == hCall) ||              // active call disconnected or
            (g_Data.hHoldCall == hCall) ||          // held call disconnected or
            (g_Data.hOfferingCall == hCall)) {      // offering call disconnected
            
            if (g_Data.hCall == hCall) {
                g_Data.hCall = NULL;
            }
            else if (g_Data.hHoldCall == hCall) {
                g_Data.hHoldCall = NULL;
            }
            else if (g_Data.hOfferingCall == hCall) {
                g_Data.hOfferingCall = NULL;
            }

            if (NETWORK_STATE_RINGING == g_Data.dwState) {
                DEBUGMSG(ZONE_NETWORK, (L"BTAGSVC: Network - Reject call.\n"));
                TapiUnlock();
                BthAGOnNetworkEvent(NETWORK_EVENT_CALL_REJECT, NULL, 0);
                TapiLock();
            }
            else {
                DEBUGMSG(ZONE_NETWORK, (L"BTAGSVC: Network - Hang-up call.\n"));    
                
                DWORD dwCalls = (g_Data.hCall ? 1 : 0) + (g_Data.hHoldCall ? 1 : 0) + (g_Data.hOfferingCall ? 1 : 0);
                
                TapiUnlock();
                if (LINEDISCONNECTMODE_BUSY == pMsg->dwParam2) {
                    BthAGOnNetworkEvent(NETWORK_EVENT_CALL_BUSY, (LPVOID)dwCalls, sizeof(DWORD));
                }
                else {
                    BthAGOnNetworkEvent(NETWORK_EVENT_CALL_DISCONNECT, (LPVOID)dwCalls, sizeof(DWORD));
                }
                TapiLock();
            }

            if (g_Data.hCall) {
                g_Data.dwState = NETWORK_STATE_INCALL;
            }
            else if (g_Data.hHoldCall) {
                g_Data.dwState = NETWORK_STATE_ONHOLD;
            }
            else {
                g_Data.dwState = NETWORK_STATE_DISCONNECTED;
            }
        }
    }
    else if (LINECALLSTATE_BUSY == pMsg->dwParam1) {
        if (g_Data.hOfferingCall == hCall) {
            // Busy
            DEBUGMSG(ZONE_NETWORK, (L"BTAGSVC: Network - Busy signal.\n"));
            g_Data.hOfferingCall = NULL;

            DWORD dwCalls = (g_Data.hCall ? 1 : 0) + (g_Data.hHoldCall ? 1 : 0) + (g_Data.hOfferingCall ? 1 : 0);

            TapiUnlock();
            BthAGOnNetworkEvent(NETWORK_EVENT_CALL_BUSY, (LPVOID)dwCalls, sizeof(DWORD));
            TapiLock();

            if (g_Data.hHoldCall) {
                g_Data.dwState = NETWORK_STATE_ONHOLD;
            }
            else {
                g_Data.dwState = NETWORK_STATE_DISCONNECTED;
            }
        }
    }
    else if (LINECALLSTATE_CONNECTED == pMsg->dwParam1) {                
        if (g_Data.hOfferingCall == hCall) {
            DEBUGMSG(ZONE_NETWORK, (L"BTAGSVC: Network - Offering call connected.\n"));            

            if (g_Data.hCall) {
                // If we already have an active call, it will be going on hold
                g_Data.hHoldCall = g_Data.hCall;
            }

            g_Data.hCall = hCall;
            g_Data.hOfferingCall = NULL;

            TapiUnlock();
            BthAGOnNetworkEvent(NETWORK_EVENT_CALL_CONNECT, NULL, 0);
            TapiLock();

            g_Data.dwState = NETWORK_STATE_INCALL;
        }
        else if (g_Data.hHoldCall == hCall) {
            DEBUGMSG(ZONE_NETWORK, (L"BTAGSVC: Network - Held call connected.\n")); 
            
            g_Data.hHoldCall = g_Data.hCall;
            g_Data.hCall = hCall;
            g_Data.dwState = NETWORK_STATE_INCALL;
        }
        else if (g_Data.hCall == hCall) {
            g_Data.dwState = NETWORK_STATE_INCALL;
        }
    }
    else if (LINECALLSTATE_ONHOLD == pMsg->dwParam1) {
        // Call put on hold
        DEBUGMSG(ZONE_NETWORK, (L"BTAGSVC: Network - Call put on hold.\n"));
        
        if ((g_Data.hCall == hCall) && g_Data.hHoldCall) {
            // If we already have a call on hold, it must be becoming active
            g_Data.hCall = g_Data.hHoldCall;
        }
        else if (g_Data.hCall == hCall) {
            // An active call is placed on hold
            g_Data.hCall = NULL;
            g_Data.dwState = NETWORK_STATE_ONHOLD;
        }

        g_Data.hHoldCall = hCall;
    }
    else if (LINECALLSTATE_DIALING == pMsg->dwParam1) {
        // Outgoing call
        DEBUGMSG(ZONE_NETWORK, (L"BTAGSVC: Network - outgoing call.\n"));
        
        g_Data.hOfferingCall = hCall;
        g_Data.dwLastRingTime = 0;

        if (g_Data.dwState == NETWORK_STATE_DISCONNECTED) {
            g_Data.dwState = NETWORK_STATE_CONNECTED;
        }

        LONG lErr = lineSetCallPrivilege(g_Data.hOfferingCall, LINECALLPRIVILEGE_OWNER);
        if (0 != lErr) {
            DEBUGMSG(ZONE_WARN, (L"BTAGSVC: Network - Error calling lineSetCallPrivilege: %d.\n", lErr));
        }
        
        TapiUnlock();
        BthAGOnNetworkEvent(NETWORK_EVENT_CALL_OUT, NULL, 0);
        TapiLock();
    }
    else if (LINECALLSTATE_OFFERING == pMsg->dwParam1) {
        // Incoming call
        DEBUGMSG(ZONE_NETWORK, (L"BTAGSVC: Network - incoming call.\n"));
            
        CHAR szNumber[MAX_PHONE_NUMBER];
        szNumber[0] = 0; // Null terminate

        g_Data.fCallIdNotify = FALSE;

        DWORD cbWritten = 0;
        if (g_Data.pCallInfo->dwCallerIDOffset > 0) {
            cbWritten = WideCharToMultiByte(CP_ACP, 0, 
                            (WCHAR*)((BYTE*)g_Data.pCallInfo + g_Data.pCallInfo->dwCallerIDOffset), 
                            g_Data.pCallInfo->dwCallerIDSize/2,
                            szNumber,
                            MAX_PHONE_NUMBER,
                            NULL, NULL);

            g_Data.fCallIdNotify = TRUE;
        }
        
        g_Data.hOfferingCall = hCall;
        g_Data.dwLastRingTime = 0;

        if (g_Data.dwState == NETWORK_STATE_DISCONNECTED) {
            g_Data.dwState = NETWORK_STATE_CONNECTED;
        }
        
        LONG lErr = lineSetCallPrivilege(g_Data.hOfferingCall, LINECALLPRIVILEGE_OWNER);
        if (0 != lErr) {
            DEBUGMSG(ZONE_WARN, (L"BTAGSVC: Network - Error calling lineSetCallPrivilege: %d.\n", lErr));
        }
        
        TapiUnlock();
        BthAGOnNetworkEvent(NETWORK_EVENT_CALL_IN, szNumber, cbWritten);
        TapiLock();
    }     

exit:    
    if ((LINECALLSTATE_IDLE == pMsg->dwParam1) || 
        (LINECALLSTATE_DISCONNECTED == pMsg->dwParam1)) {

        // Call has gone away - must deallocate the call handle that TAPI created for us in LINE_APPNEWCALL
        lineDeallocateCall(hCall);
    }
    return;
}


typedef void (*PFNEVENTPROC)(LPLINEMESSAGE pMsg);

typedef struct _TAPI_EVENT_TBL {
    DWORD dwCommand;
    PFNEVENTPROC pfnHandler;
} TAPI_EVENT_TBL, *PTAPI_EVENT_TBL;

const TAPI_EVENT_TBL TapiEventTable[] = {
    LINE_LINEDEVSTATE, TapiEventDevStateChange,
    LINE_CALLINFO, TapiEventCallInfo,
    LINE_REPLY, TapiEventLineReply,
    LINE_CALLSTATE, TapiEventCallStateChange,    
};

#define TAPI_EVENT_TBL_LENGTH     (sizeof(TapiEventTable)/sizeof(TAPI_EVENT_TBL))

//
// This function is a thread that listens for messages from TAPI and processes them.
//
DWORD WINAPI TapiEventThread(LPVOID pv)
{
    DEBUGMSG(ZONE_NETWORK, (L"BTAGSVC: ++TapiEventThread\n"));

    TapiLock();
    
    while (! g_Data.fShutdown) {
        LONG lResult;
        DWORD dwWait;
        HANDLE h = g_Data.hTapiEvent;
        LINEMESSAGE msg;
        
        TapiUnlock();
        dwWait = WaitForSingleObject(h, INFINITE);
        TapiLock();

        if (g_Data.fShutdown) {
            DEBUGMSG(ZONE_NETWORK, (L"BTAGSVC: Network - Shutting down TapiEventThread.\n"));
            break;
        }

        lResult = lineGetMessage(g_Data.hLineApp, &msg, 0);
        if (lResult != 0) {
            ASSERT(0);
            continue;
        }

        for (int i = 0; i < TAPI_EVENT_TBL_LENGTH; i++) {
            if (msg.dwMessageID == TapiEventTable[i].dwCommand) {
                TapiEventTable[i].pfnHandler(&msg);
                break;
            }
        }
    }

    if (g_Data.pCallInfo) {
        delete[] g_Data.pCallInfo;
        g_Data.pCallInfo = NULL;
    }

    TapiUnlock();

    DEBUGMSG(ZONE_NETWORK, (L"BTAGSVC: --TapiEventThread\n"));
    
    return 0;
}


//
// This function is called to initialize the AG's Network Component.
//
DWORD BthAGNetworkInit(HINSTANCE hInstance)
{
    DWORD dwRetVal = ERROR_SUCCESS;
    DWORD cLines;
    HKEY hk;
    unsigned int uiCellLine;    
    LINEINITIALIZEEXPARAMS LineInitializeExParams;
    DWORD dwVersion = TAPI_API_HIGH_VERSION;
    WCHAR wszName[MAX_PATH];
    BOOL fUseDefaultLine = TRUE;

    DEBUGMSG(ZONE_NETWORK, (L"BTAGSVC: ++BthAGNetworkInit\n"));

    if (InterlockedExchange(&g_Inited, 1)) {
        return dwRetVal;
    }

    TapiLock();

    LineInitializeExParams.dwTotalSize = sizeof(LineInitializeExParams);
    LineInitializeExParams.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT;    
    dwRetVal = lineInitializeEx(&g_Data.hLineApp, hInstance, NULL, L"BTAGSVC", &cLines, &dwVersion, &LineInitializeExParams);
    if (ERROR_SUCCESS != dwRetVal) {
        ASSERT(0);
        goto exit;
    }

    g_Data.hTapiEvent = LineInitializeExParams.Handles.hEvent;

    g_Data.hThread = CreateThread(NULL, 0, TapiEventThread, NULL, 0, NULL);
    if (! g_Data.hThread) {
        ASSERT(0);
        goto exit;
    }

    if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, RK_AUDIO_GATEWAY, 0, 0, &hk)) {        
        DWORD cdwBytes = MAX_PATH;
        if (ERROR_SUCCESS == RegQueryValueEx(hk, _T("TapiLineName"), 0, NULL, (PBYTE)wszName, &cdwBytes)) {
            fUseDefaultLine = FALSE;
        }

        RegCloseKey(hk);
    }

    if (fUseDefaultLine) {
        dwRetVal = FindTSPLine(DEFAULT_TAPI_CELL_LINE, cLines, &uiCellLine);
    }
    else {
        dwRetVal = FindTSPLine(wszName, cLines, &uiCellLine);
    }
    
    if (ERROR_SUCCESS != dwRetVal) {
        DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Error finding cellular line: %d\n", dwRetVal));
        goto exit;
    }

    dwRetVal = OpenLine(uiCellLine);
    if (ERROR_SUCCESS != dwRetVal) {
        DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Error opening line: %d\n", dwRetVal));
        goto exit;
    }

    // Specify additional messages we would like to receive in TapiEventThread
    dwRetVal = lineSetStatusMessages(g_Data.hLine, 
        LINEDEVSTATE_RINGING | LINEDEVSTATE_CONNECTED | LINEDEVSTATE_DISCONNECTED, 
        0);
    if (ERROR_SUCCESS != dwRetVal) {
        DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Error setting line status messages: %d\n", dwRetVal));
        goto exit;
    }

    g_Data.dwWaitTimeout = TAPI_COMMAND_TIMEOUT;

    if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, RK_AUDIO_GATEWAY, 0, 0, &hk)) {
        DWORD dwData;
        DWORD cdwBytes = sizeof(dwData);
        if (ERROR_SUCCESS == RegQueryValueEx(hk, _T("TapiAsyncTimeoutSeconds"), 0, NULL, (PBYTE)&dwData, &cdwBytes)) {
            g_Data.dwWaitTimeout = (dwData * 1000);
        }

        RegCloseKey(hk);
    }

    DEBUGMSG(ZONE_NETWORK, (L"BTAGSVC: Network Module was successfullly initialized.\n"));

exit:
    TapiUnlock();
    
    if (ERROR_SUCCESS != dwRetVal) {
        BthAGNetworkDeinit();
    }

    DEBUGMSG(ZONE_NETWORK, (L"BTAGSVC: --BthAGNetworkInit\n"));
    
    return dwRetVal;
}


//
// This function deinitializes the AG's Network Component.
//
void BthAGNetworkDeinit(void)
{
    DEBUGMSG(ZONE_NETWORK, (L"BTAGSVC: ++BthAGNetworkDeinit\n"));

    if (0 == g_Inited) {
        return; // Not initialized
    }

    TapiLock();
    
    if (g_Data.hThread) {
        HANDLE h = g_Data.hThread;
        g_Data.fShutdown = TRUE;
        SetEvent(g_Data.hTapiEvent);

        TapiUnlock();
        WaitForSingleObject(h, INFINITE);
        TapiLock();

        while (g_Data.GetRefCount() > 1) {
            DEBUGMSG(ZONE_NETWORK, (L"BTAGSVC: Sleeping while Tapi Network Component ref count is still active.\n"));
            TapiUnlock();
            Sleep(500);
            TapiLock();
        }

        // Wait for all calls to return
        int count = 0;
        while ((count++ > 10) && g_Data.CallList.size()) {
            DEBUGMSG(ZONE_NETWORK, (L"BTAGSVC: Sleeping a bit since all Tapi calls have not been returned.\n"));
            TapiUnlock();
            Sleep(500);
            TapiLock();
        }

        // If not all calls have returned by this point, remove them
        if (g_Data.CallList.size()) {
            DEBUGMSG(ZONE_WARN, (L"BTAGSVC: Forcefully deleting remaining Tapi calls\n"));
            g_Data.CallList.clear();
        }

        CloseHandle(h);
    }

    lineClose(g_Data.hLine);
    lineShutdown(g_Data.hLineApp);

    TapiUnlock();

    InterlockedExchange(&g_Inited, 0);
    
    DEBUGMSG(ZONE_NETWORK, (L"BTAGSVC: --BthAGNetworkDeinit\n"));
}


//
// This function dials a number through TAPI.
//
DWORD BthAGNetworkDialNumber(LPWSTR pwszNumber)
{

⌨️ 快捷键说明

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