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

📄 handler.cpp

📁 WinCE5.0部分核心源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//

#include <windows.h>
#include <initguid.h>
#include <bt_sdp.h>

#include "btagpriv.h"
#include "btagnetwork.h"

#ifndef PREFAST_ASSERT
#define PREFAST_ASSERT(x) ASSERT(x)
#endif


#define AT_OK       "\r\nOK\r\n"
#define AT_ERROR    "\r\nERROR\r\n"
#define AT_VGS      "\r\n+VGS=%d\r\n"
#define AT_VGM      "\r\n+VGM=%d\r\n"
#define AT_RING     "\r\nRING\r\n"


void PhoneExtServiceCallback(BOOL fHaveService);

BOOL IsHandsfreeUUID(const GUID* pGuid)
{
    ASSERT(pGuid);
    return !memcmp(pGuid, &HandsfreeServiceClass_UUID, sizeof(*pGuid));
}

CAGEngine::CAGEngine(void)
{
}


// This method initializes the AG engine
DWORD CAGEngine::Init(CATParser* pParser)
{
    DWORD dwRetVal = ERROR_SUCCESS;

    DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: AG Engine is being initialized.\n"));

    Lock();

    ASSERT(pParser);
    
    m_pParser = pParser;
    m_fExpectHeadsetButton = FALSE;
    m_fAudioConnect = FALSE;
    m_hSco = 0;
    m_hUIThread = NULL;
    m_fPhoneExtInited = FALSE;
    m_fNetworkInited = FALSE;
    m_wszCLI[0] = 0;
    m_fCancelCloseConnection = FALSE;
    m_CloseCookie = NULL;
    m_SniffCookie = NULL;

    memset(&m_AGProps, 0, sizeof(AG_PROPS));

    m_AGProps.fPCMMode = TRUE;
    m_AGProps.usMicVolume = 8;
    m_AGProps.usSpeakerVolume = 8;
    m_AGProps.fAuth = TRUE;
    m_AGProps.fEncrypt = TRUE;
    m_AGProps.usHFCapability = DEFAULT_AG_CAPABILITY;
    m_AGProps.usPageTimeout = DEFAULT_PAGE_TIMEOUT;
    m_AGProps.ulSniffDelay = DEFAULT_SNIFF_DELAY;
    m_AGProps.usSniffMax = DEFAULT_SNIFF_MAX;
    m_AGProps.usSniffMin = DEFAULT_SNIFF_MIN;    
    m_AGProps.usSniffAttempt = DEFAULT_SNIFF_ATTEMPT;
    m_AGProps.usSniffTimeout = DEFAULT_SNIFF_TO;

    m_pTP = new SVSThreadPool(2);
    if (! m_pTP) {
        Unlock();
        return ERROR_OUTOFMEMORY;
    }

    DWORD dwErr = BthAGNetworkInit(g_hInstance);
    if (ERROR_SUCCESS != dwErr) {
        // This is not a critical failure, continue to load service.
        DEBUGMSG(ZONE_WARN, (L"BTAGSVC: Error initializing network module: %d.\n", dwErr));        
    }
    else {
        m_fNetworkInited = TRUE;
    }    

    dwErr = BthAGPhoneExtInit();
    if (ERROR_SUCCESS != dwErr) {
        // This is not a critical failure, continue to load service.
        DEBUGMSG(ZONE_WARN, (L"BTAGSVC: Error initializing PhoneExt module: %d.\n", dwErr));        
    }
    else {
        m_fPhoneExtInited = TRUE;
    }

    Unlock();
    
    if (ERROR_SUCCESS != BthAGSetServiceCallback(PhoneExtServiceCallback)) {
        DEBUGMSG(ZONE_WARN, (L"BTAGSVC: Error setting service callback in PhoneExt.\n"));
    }

    return dwRetVal;
}


// This method deinitializes the AG engine
void CAGEngine::Deinit(void)
{
    DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: AG Engine is being de-initialized.\n"));

    Lock();

    if (m_pParser) {
        CloseAudioChannel();
        CloseControlChannel();

        if (m_fPhoneExtInited) {
            BthAGPhoneExtDeinit();
        }

        if (m_fNetworkInited) {
            BthAGNetworkDeinit();
        }

        delete m_pTP;
        m_pTP = NULL;

        memset(&m_AGProps, 0, sizeof(AG_PROPS));    
        m_pParser = NULL;

        while (GetRefCount() > 1) {
            DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Sleeping while AGEngine ref count is still active.\n"));
            Unlock();
            Sleep(500);
            Lock();
        }
    }
    
    Unlock();    
}


//
// This function gets the list of HF devices from the registry
//
DWORD GetBTAddrList(AG_DEVICE* pDevices, const USHORT usNumDevices)
{
    DWORD dwRetVal = ERROR_SUCCESS;
    HKEY hk = NULL;
    int dwIdx = 0;
    WCHAR szName[MAX_PATH];
    DWORD cchName = ARRAY_SIZE(szName);

    ASSERT(pDevices && usNumDevices);

    // Clear the current list
    memset(pDevices, 0, usNumDevices*sizeof(pDevices[0]));

    dwRetVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE, RK_AUDIO_GATEWAY_DEVICES, 0, 0, &hk);
    if (ERROR_SUCCESS != dwRetVal) {
        DEBUGMSG(ZONE_WARN, (L"BTAGSVC: Could not open registry key for BT Addr: %d.\n", dwRetVal));        
        goto exit;
    }

    // Enumerate devices in registry    
    while (ERROR_SUCCESS == RegEnumKeyEx(hk, dwIdx, szName, &cchName, NULL, NULL, NULL, NULL)) {
        HKEY hkAddr;
        BT_ADDR btAddr = 0;
        GUID service;
        DWORD cdwSize;
        
        DWORD dwErr = RegOpenKeyEx(hk, szName, 0, 0, &hkAddr);
        if (ERROR_SUCCESS != dwErr) {
            DEBUGMSG(ZONE_WARN, (L"BTAGSVC: Could not open registry key for BT Addr: %d.\n", dwRetVal));        
            break;
        }
        
        cdwSize = sizeof(btAddr);
        dwErr = RegQueryValueEx(hkAddr, L"Address", NULL, NULL, (PBYTE)&btAddr, &cdwSize);
        if (dwErr != ERROR_SUCCESS) {
            DEBUGMSG(ZONE_WARN, (L"BTAGSVC: Could not query registry value for BT Addr: %d.\n", dwErr));        
            RegCloseKey(hkAddr);
            break;
        }

        cdwSize = sizeof(service);
        dwErr = RegQueryValueEx(hkAddr, L"Service", NULL, NULL, (PBYTE)&service, &cdwSize);
        if (dwErr != ERROR_SUCCESS) {
            DEBUGMSG(ZONE_WARN, (L"BTAGSVC: Could not query registry value for service: %d.\n", dwErr));        
            RegCloseKey(hkAddr);
            break;
        }        

        RegCloseKey(hkAddr);

        WCHAR* p;
        int iDeviceIdx = wcstol(szName, &p, 10);
        if (btAddr != 0 && ((iDeviceIdx >= 1) || (iDeviceIdx <= usNumDevices))) {
            DEBUGMSG(ZONE_OUTPUT, (L"BTAGSVC: Setting btAddr at index %d to %04x%08x.\n", iDeviceIdx, GET_NAP(btAddr), GET_SAP(btAddr))); 
            pDevices[iDeviceIdx-1].bta = btAddr;
            memcpy(&pDevices[iDeviceIdx-1].service, &service, sizeof(GUID));
        }

        cchName = ARRAY_SIZE(szName);
        dwIdx++;        
    }    

    RegCloseKey(hk);

exit:
    
    return dwRetVal;
}


BOOL CAGEngine::FindBTAddrInList(const BT_ADDR btaSearch)
{
    BOOL fRetVal = FALSE;

    Lock();

    GetBTAddrList(m_AGProps.DeviceList, ARRAY_SIZE(m_AGProps.DeviceList)); // Update from registry

    // Loop through list until we find the address
    int i = 0;
    while ((i < ARRAY_SIZE(m_AGProps.DeviceList)) && (btaSearch != m_AGProps.DeviceList[i].bta)) {
        i++;
    }

    if (i < ARRAY_SIZE(m_AGProps.DeviceList)) {
        fRetVal = TRUE;
    }

    Unlock();
    
    return fRetVal;
}



// This method writes the address list back to the registry
// sets the parameter btAddrDefault at the top of the list
// and as the active device.
DWORD CAGEngine::SetBTAddrList(BT_ADDR btAddrDefault, BOOL fHfSupport)
{
    DWORD       dwRetVal    = ERROR_SUCCESS;
    DWORD       dwDis       = 0;
    HKEY        hk          = NULL;

    Lock();

    GetBTAddrList(m_AGProps.DeviceList, ARRAY_SIZE(m_AGProps.DeviceList)); // Update from registry

    m_AGProps.btAddrClient = btAddrDefault;

    // Loop through list until we find the address
    int i = 0;
    while ((i < ARRAY_SIZE(m_AGProps.DeviceList)) && (btAddrDefault != m_AGProps.DeviceList[i].bta)) {
        i++;
    }
    
    if (i > 0) {
        GUID service;
        
        if (i == ARRAY_SIZE(m_AGProps.DeviceList)) {
            // This is a very unlikely scenario.  We get a connection request after pairing
            // with the device but before SDP is done.
            service = fHfSupport ? HandsfreeServiceClass_UUID : HeadsetServiceClass_UUID;
        }
        else {
            service = m_AGProps.DeviceList[i].service;
        }

        memmove(&m_AGProps.DeviceList[1], m_AGProps.DeviceList, i*sizeof(AG_DEVICE));
        
        m_AGProps.DeviceList[0].bta = btAddrDefault;
        m_AGProps.DeviceList[0].service = service;
    }

    // Write the list back to the registry
    dwRetVal = RegCreateKeyEx(HKEY_LOCAL_MACHINE, RK_AUDIO_GATEWAY_DEVICES, 0, NULL, 0, NULL, NULL, &hk, &dwDis);
    if (ERROR_SUCCESS == dwRetVal) {
        int dwIdx = 0;
        DWORD cbName = MAX_PATH;

        while ((dwIdx < ARRAY_SIZE(m_AGProps.DeviceList)) && m_AGProps.DeviceList[dwIdx].bta != 0) {
            HKEY hkAddr;
            WCHAR wszIdx[10];            
            _itow(dwIdx+1, wszIdx, 10);

            dwDis = 0;
            DWORD dwErr = RegCreateKeyEx(hk, wszIdx, 0, NULL, 0, NULL, NULL, &hkAddr, &dwDis);
            if (ERROR_SUCCESS != dwErr) {
                DEBUGMSG(ZONE_WARN, (L"BTAGSVC: Could not open registry key for BT Addr: %d.\n", dwRetVal));        
                break;
            }
                
            dwErr = RegSetValueEx(hkAddr, L"Address", NULL, REG_BINARY, (PBYTE)&m_AGProps.DeviceList[dwIdx].bta, sizeof(BT_ADDR));
            if (dwErr != ERROR_SUCCESS) {
                RegCloseKey(hkAddr);
                DEBUGMSG(ZONE_WARN, (L"BTAGSVC: Could not set registry value for BT Addr: %d.\n", dwErr));        
                break;
            }

            dwErr = RegSetValueEx(hkAddr, L"Service", NULL, REG_BINARY, (PBYTE)&m_AGProps.DeviceList[dwIdx].service, sizeof(GUID));
            if (dwErr != ERROR_SUCCESS) {
                RegCloseKey(hkAddr);
                DEBUGMSG(ZONE_WARN, (L"BTAGSVC: Could not set registry value for service: %d.\n", dwErr));        
                break;
            }

            DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Saving to registry btAddr %04x%08x at index %d.\n", GET_NAP(m_AGProps.DeviceList[dwIdx].bta), GET_SAP(m_AGProps.DeviceList[dwIdx].bta), dwIdx+1));

            RegCloseKey(hkAddr);
            
            dwIdx++;        
        }

        RegCloseKey (hk);
    }

    Unlock();

    return dwRetVal;
}


// This method notifies the AG Engine that a connection has been made with a peer
DWORD CAGEngine::NotifyConnect(SOCKET sockClient, BOOL fHFSupport)
{
    DWORD dwRetVal = ERROR_SUCCESS;
    
    Lock();
    
    if (m_AGProps.state >= AG_STATE_CONNECTED) {
        dwRetVal = ERROR_ALREADY_INITIALIZED;
        goto exit;
    }

    m_AGProps.state = AG_STATE_CONNECTING;

    if (m_pParser) {
        dwRetVal = m_pParser->Start(this, sockClient);        
    }
    else {
        dwRetVal = ERROR_NOT_READY;
    }
    if (ERROR_SUCCESS != dwRetVal) {
        DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Error starting parser module: %d\n", dwRetVal)); 
        goto exit;
    }

    ASSERT(INVALID_SOCKET != sockClient);
    
    m_sockClient = sockClient;

    AddRef();
    Unlock();
    
    BthAGPhoneExtEvent(AG_PHONE_EVENT_BT_CTRL, 1, NULL);

    Lock();
    DelRef();   

    m_fAudioConnect = FALSE;

    m_AGProps.fHandsfree = fHFSupport;    
    
    if (!m_AGProps.fHandsfree) {
        // For headset devices, connect audio after we have made
        // an RFCOMM connection.
        m_fExpectHeadsetButton = TRUE;
        m_AGProps.state = AG_STATE_CONNECTED;
        dwRetVal = OpenAudioChannel();
    }
   
exit:
    if (ERROR_SUCCESS != dwRetVal) {
        CloseControlChannel();
    }
    
    Unlock();
    return dwRetVal;
}


// This method is called when a connection event occurs
void CAGEngine::ConnectionEvent(void)
{
    BASEBAND_CONNECTION connections[5];
    int cConnectionsIn = 5;
    int cConnectionsOut = 0;
                
    DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: ConnectionEvent.\n"));

    //
    // Ensure SCO is in the correct state
    //
    
    Lock();

    BASEBAND_CONNECTION* pConnections = connections;
    int iErr;
    do {
        if (cConnectionsOut > cConnectionsIn) {
            if (pConnections != connections)
                delete[] pConnections;
            pConnections = new BASEBAND_CONNECTION[cConnectionsOut];
            if (! pConnections) {                            
                break;
            }
            cConnectionsIn = cConnectionsOut;
        }
        iErr = BthGetBasebandConnections(cConnectionsIn, pConnections, &cConnectionsOut);                    
    } while (ERROR_INSUFFICIENT_BUFFER == iErr);

    if (ERROR_SUCCESS == iErr) {   
        BOOL fScoPresent = FALSE;
       
        for (int i = 0; i < cConnectionsOut; i++) {
            if ((pConnections[i].baAddress == m_AGProps.btAddrClient) && 
            (0 == pConnections[i].fLinkType) && 
            (m_AGProps.state >= AG_STATE_CONNECTED)
            ) {
                // SCO link with same address as ACL connection
                NotifySCOConnect(pConnections[i].hConnection);
                fScoPresent = TRUE;
                break;
            }
        }

⌨️ 快捷键说明

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