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

📄 handler.cpp

📁 WinCE5.0部分核心源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:

        if (! fScoPresent) {
            ClearSCO();
        }
    }

    if (pConnections != connections)
        delete[] pConnections;    

    Unlock();    
}


// This method notifies the AG Engine that a SCO connection has been made with a peer
DWORD CAGEngine::NotifySCOConnect(unsigned short handle)
{
    DWORD dwRetVal = ERROR_SUCCESS;

    DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: ++NotifySCOConnect.\n"));
    
    ASSERT(IsLocked());
    
    if (m_AGProps.state >= AG_STATE_AUDIO_UP) {
        DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: NotifySCOConnect - Audio connection already opened.\n"));
        m_AGProps.state = AG_STATE_AUDIO_UP;
        dwRetVal = ERROR_ALREADY_INITIALIZED;
        goto exit;
    }

    if (m_AGProps.state < AG_STATE_CONNECTED) {
        DEBUGMSG(ZONE_WARN, (L"BTAGSVC: NotifySCOConnect - Cannot open audio connection until service-level connection has been made.\n"));
        dwRetVal = ERROR_NOT_READY;
        goto exit;        
    }

    // TODO: See if we have a built-in audio driver and do switching.
    
    waveOutMessage(0, WODM_BT_SCO_AUDIO_CONTROL, 0, TRUE);

    if (m_AGProps.fPCMMode) {
        m_hSco = handle;
    }

    m_AGProps.state = AG_STATE_AUDIO_UP;

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

    Lock();
    DelRef();

exit:
    DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: --NotifySCOConnect.\n"));
    
    return dwRetVal;
}


// This method informs the AG that no SCO connections to the device are present.  We need to
// make sure that audio state is no longer up.
void CAGEngine::ClearSCO(void)
{
    BOOL fClearSCO = FALSE;
    
    ASSERT(IsLocked());
    
    if (AG_STATE_AUDIO_UP == m_AGProps.state) {
        DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: SCO connection was closed.\n"));
        m_AGProps.state = AG_STATE_CONNECTED;
        fClearSCO = TRUE;
    }
    else if (AG_STATE_RINGING_AUDIO_UP == m_AGProps.state) {
        DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: SCO connection was closed.\n"));
        m_AGProps.state = AG_STATE_RINGING;
        fClearSCO = TRUE;
    }

    if (fClearSCO) {
        waveOutMessage(0, WODM_BT_SCO_AUDIO_CONTROL, 0, FALSE);

        // TODO: See if we have a built-in audio driver and do switching.
        
        m_hSco = 0;

        AddRef();
        Unlock();

        BthAGPhoneExtEvent(AG_PHONE_EVENT_BT_AUDIO, 0, NULL);

        Lock();
        DelRef();  

        // If we have not already scheduled sniff thread and sniff mode is enabled and we
        // are connected to a HF device and are persisting HF connections, schedule the
        // sniff thread.
        if ((! m_SniffCookie) && m_AGProps.ulSniffDelay && m_AGProps.fHandsfree && !m_AGProps.fPowerSave) {
            m_SniffCookie = m_pTP->ScheduleEvent(EnterSniffModeThread, (LPVOID)this, m_AGProps.ulSniffDelay);        
        }
    }
}


// This method instructs the AG Engine to open a connection
DWORD CAGEngine::OpenAGConnection(BOOL fOpenAudio, BOOL fFirstOnly)
{
    DWORD dwRetVal = ERROR_SUCCESS;

    DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Opening AG connection.\n"));

    Lock();

    m_fAudioConnect = fOpenAudio;
    dwRetVal = OpenControlChannel(fFirstOnly);
    
    Unlock();
    
    return dwRetVal;
}


// This private method opens control connection to peer
DWORD CAGEngine::OpenControlChannel(BOOL fFirstOnly)
{
    DWORD           dwRetVal = ERROR_SUCCESS;
    SOCKADDR_BTH    sa;
    DWORD           dwDeviceIdx = 0;
    USHORT          usPageTimeout;

    DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Opening control connection.\n"));

    ASSERT(IsLocked());
    
    if (m_AGProps.state >= AG_STATE_CONNECTED) {
        // Make sure we are not timing out the connection
        m_pTP->UnScheduleEvent(m_CloseCookie);
        m_CloseCookie = NULL;
        m_fCancelCloseConnection = FALSE;
        
        if (m_fAudioConnect) {
            DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Already connected, just opening audio connection.\n")); 
            m_fAudioConnect = FALSE;
            dwRetVal = OpenAudioChannel();
        }
        else {
            DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: OpenControlConnection returning ERROR_ALREADY_INITIALIZED\n")); 
            dwRetVal = ERROR_ALREADY_INITIALIZED;
        }
        
        goto exit;
    }

    usPageTimeout = m_AGProps.usPageTimeout;
    if (fFirstOnly) {
        // If we are only connecting to the pri-1 device, let's allow
        // for a longer time out.
        usPageTimeout *= 2;
    }

    (void) BthWritePageTimeout(usPageTimeout); // if this fails, we continue anyway    

    m_sockClient = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
    if (INVALID_SOCKET == m_sockClient) {
        dwRetVal = GetLastError();
        DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Error opening socket: %d\n", dwRetVal)); 
        goto exit;
    }

    (void) GetBTAddrList(m_AGProps.DeviceList, ARRAY_SIZE(m_AGProps.DeviceList)); // if this fails, we continue anyway

    if (m_AGProps.DeviceList[0].bta == 0) {
        DEBUGMSG(ZONE_WARN, (L"BTAGSVC: Tried to open a connection but no device has been paired yet.\n"));
        dwRetVal = ERROR_NOT_READY;
        goto exit;
    }

    while (dwDeviceIdx < ARRAY_SIZE(m_AGProps.DeviceList)) {
        if (m_AGProps.DeviceList[dwDeviceIdx].bta == 0) {
            DEBUGMSG(ZONE_WARN, (L"BTAGSVC: Device with index %d does not exist, failed to connect.\n", dwDeviceIdx));
            dwRetVal = ERROR_NOT_READY;
            goto exit;
        }

        BOOL fHS = m_AGProps.fNoHandsfree || !IsHandsfreeUUID(&(m_AGProps.DeviceList[dwDeviceIdx].service));
        
        memset(&sa, 0, sizeof(sa));
        sa.addressFamily = AF_BTH;
        sa.btAddr = m_AGProps.DeviceList[dwDeviceIdx].bta;

        if (fHS) {
            // Try to connect to a headset
            DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: OpenControlConnection - Attempting to connect to headset device at index %d.\n", dwDeviceIdx));
            sa.serviceClassId = HeadsetServiceClass_UUID;
        }
        else {
            // Try to connect to a hands-free
            DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: OpenControlConnection - Attempting to connect to HF device at index %d.\n", dwDeviceIdx));
            sa.serviceClassId = HandsfreeServiceClass_UUID;
        }        
        
        if (SOCKET_ERROR == connect(m_sockClient, (SOCKADDR *)&sa, sizeof(sa))) {
            if (fFirstOnly) {
                dwRetVal = ERROR_NOT_CONNECTED;
                goto exit;
            }
            else {
                dwDeviceIdx++;
                continue;
            }
        }

        if (fHS) {
            m_AGProps.fHandsfree = FALSE;
            DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Connected to a headset device.\n"));
        }
        else {
            m_AGProps.fHandsfree = TRUE;
            DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Connected to a hands-free device.\n"));
        }
  
        // If we get to here we are connected
        SetBTAddrList(m_AGProps.DeviceList[dwDeviceIdx].bta, m_AGProps.fHandsfree);
        break;
    }

    if (dwDeviceIdx == ARRAY_SIZE(m_AGProps.DeviceList)) {
        DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Error: Could not connect to any devices.\n"));
        dwRetVal = ERROR_NOT_CONNECTED;
        goto exit;
    }

    if (m_AGProps.fHandsfree) {
        m_AGProps.state = AG_STATE_CONNECTING;
    }
    else {
        m_fExpectHeadsetButton = FALSE;
        m_AGProps.state = AG_STATE_CONNECTED;
    }


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

    AddRef();
    Unlock();

    BthAGPhoneExtEvent(AG_PHONE_EVENT_BT_CTRL, 1, NULL);

    Lock();
    DelRef();

    if (m_fAudioConnect && !m_AGProps.fHandsfree) {
        // Open audio connection
        m_fAudioConnect = FALSE;
        dwRetVal = OpenAudioChannel();
    }

exit:
    if ((ERROR_SUCCESS != dwRetVal) && (ERROR_ALREADY_INITIALIZED != dwRetVal)) {
        CloseControlChannel();
    }
        
    return dwRetVal;
}


// This method closes the connection to the peer device
void CAGEngine::CloseAGConnection(BOOL fCloseControl)
{
    DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Closing AG connection.\n"));
    
    Lock();
    
    if (fCloseControl || !m_AGProps.fHandsfree) {
        CloseControlChannel();
    }
    else {
        CloseAudioChannel();
    }
    
    Unlock();
}


// This private method closes the control connection to the peer
void CAGEngine::CloseControlChannel(void) 
{
    ASSERT(IsLocked());

    DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: ++CloseControlChannel\n"));

    // Make sure audio connection is closed and we are unparked
    CloseAudioChannel();
    EnsureActiveBaseband();

    AddRef();
    Unlock();

    if (m_pParser) {
        m_pParser->Stop();
    }
    
    Lock();
    DelRef();

    m_sockClient = INVALID_SOCKET;  // parser will close the socket

    m_AGProps.state = AG_STATE_DISCONNECTED;
    m_AGProps.usCallType = AG_CALL_TYPE_NONE;
    m_AGProps.fHandsfree = FALSE;
    m_AGProps.fNotifyCallWait = FALSE;
    m_AGProps.fNotifyCLI = FALSE;
    m_AGProps.fIndicatorUpdates = FALSE;
    m_AGProps.btAddrClient = 0;

    DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: --CloseControlChannel\n"));
}


void CAGEngine::ServiceConnectionUp()
{
    //
    // At this point, HF is initialized
    //

    ASSERT(IsLocked());

    if (AG_STATE_CONNECTING == m_AGProps.state) {        
        // If we are still in connecting state, we are now connected.
        m_AGProps.state = AG_STATE_CONNECTED;

        if (m_AGProps.fIndicatorUpdates) {
            CHAR szCommand[MAX_SEND_BUF];
            int cbCommand;

            if (m_AGProps.fHaveService) {
                SendATCommand("\r\n+CIEV:1,1\r\n", 13);
            }

            if (m_AGProps.fInCall) {
                SendATCommand("\r\n+CIEV:2,1\r\n", 13);
            }

            cbCommand = _snprintf(szCommand, MAX_SEND_BUF-1, "\r\n+CIEV:3,%d\r\n", m_AGProps.usCallSetup);
            szCommand[MAX_SEND_BUF-1]='\0';
            if (cbCommand > 0) {
                SendATCommand(szCommand, cbCommand);
            }
        }

        if (m_fAudioConnect) {
            OpenAudioChannel();
            m_fAudioConnect = FALSE;
        }

        if (m_AGProps.usHFCapability & AG_CAP_INBAND_RING) {
            if (m_AGProps.state >= AG_STATE_AUDIO_UP) {
                SendATCommand("\r\n+BSIR:1\r\n", 11); // In-band ring tone on
            }
            else {
                SendATCommand("\r\n+BSIR:0\r\n", 11); // In-band ring tone off
            }
        }
    }
}

// This method gets AG properties
void CAGEngine::GetAGProps(PAG_PROPS pAGProps)
{
    PREFAST_ASSERT(pAGProps);

    Lock();
    *pAGProps = m_AGProps;
    Unlock();
}


// This method sets AG properties
void CAGEngine::SetAGProps(PAG_PROPS pAGProps)
{
    ASSERT((pAGProps->usSpeakerVolume >= 0) && (pAGProps->usSpeakerVolume <= 15));
    ASSERT((pAGProps->usMicVolume >= 0) && (pAGProps->usMicVolume <= 15));

    Lock();
    m_AGProps = *pAGProps;
    Unlock();
}    


// This private method opens the audio connection to the peer
DWORD CAGEngine::OpenAudioChannel(void)
{
    DWORD dwRetVal = ERROR_SUCCESS;

    DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Opening audio connection.\n"));

    ASSERT(IsLocked());
    
    if (m_AGProps.state >= AG_STATE_AUDIO_UP) {
        DEBUGMSG(ZONE_HANDLER, (L"BTAGSVC: Audio connection already opened.\n"));
        m_AGProps.state = AG_STATE_AUDIO_UP;
        dwRetVal = ERROR_ALREADY_INITIALIZED;
        goto exit;
    }

    if (m_AGProps.state < AG_STATE_CONNECTED) {
        DEBUGMSG(ZONE_WARN, (L"BTAGSVC: Cannot open audio connection until service-level connection has been made.\n"));
        dwRetVal = ERROR_NOT_READY;
        goto exit;        
    }

    EnsureActiveBaseband();

    if (m_AGProps.fPCMMode) {
        ASSERT(m_hSco == 0);
        
        dwRetVal = BthCreateSCOConnection (&m_AGProps.btAddrClient, &m_hSco);
        if (ERROR_SUCCESS != dwRetVal) {
            DEBUGMSG(ZONE_ERROR, (_T("BTAGSVC: Error creating SCO connection: %d\n"), dwRetVal));
            //retry to work around certain cases where the SCO connection seems to be oddly rejected by the HF unit
            Sleep(100);
            dwRetVal = BthCreateSCOConnection (&m_AGProps.btAddrClient, &m_hSco);
            if (ERROR_SUCCESS != dwRetVal) {
                DEBUGMSG(ZONE_ERROR, (_T("BTAGSVC: Error creating SCO connection: %d\n"), dwRetVal));            
                goto exit;
            }
        }
    }

⌨️ 快捷键说明

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