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

📄 wavepdd.cxx

📁 Windows CE操作系统中适用的蓝牙驱动程序
💻 CXX
📖 第 1 页 / 共 4 页
字号:
		    m8 = ((UINT8) (M >> 8)) ^ 0x80;
		}
		
		*pDst++ = m8;
	}
}


// -----------------------------------------------------------------------------
//                      ExtractFromWaveBuffers
// -----------------------------------------------------------------------------
//  Copies data from wave buffers to given buffer
//  returns amount of data copied
// -----------------------------------------------------------------------------
static DWORD
ExtractFromWaveBuffers(
    PWAVEHDR    pwh,
    PBYTE       pBuffer,
    DWORD       dwBufferLen
    )
{	
    DWORD dwTotalBytes = 0;
    DWORD dwWaveBufferLen = dwBufferLen * 4;
    
    while ( (dwWaveBufferLen > 0) && (pwh != NULL)) 
    {
        if (pwh->dwBytesRecorded >= pwh->dwBufferLength) {
            pwh = pwh->lpNext;
            continue;
        }

        // trasfer min(data_in_wavebuffer, room_in_pBuffer)
        ULONG ulBytesCopied = pwh->dwBufferLength - pwh->dwBytesRecorded;
        if ( ulBytesCopied > dwWaveBufferLen ) {
            ulBytesCopied = dwWaveBufferLen;
        }

        /* 
        PWAVEHDR pTest = pwh;
        DWORD dwTestBytes = pTest->dwBufferLength - pTest->dwBytesRecorded;        
        while(pTest->lpNext) {
            pTest = pTest->lpNext;
            dwTestBytes += pTest->dwBufferLength - pTest->dwBytesRecorded;
        }
        DEBUGMSG(1, (_T("=== BT Audio Driver Module: ExtractFromWaveBuffers. Total_Size=%u. GetTickCount=%u. ===\n"), dwTestBytes, GetTickCount()));
        */

		// Convert from 16-bit stereo to 8-bit mono
		ASSERT((ulBytesCopied % 4) == 0);
		DWORD dwSamples = ulBytesCopied/4;
		ConvertS16toM08((UINT32*)(pwh->lpData + pwh->dwBytesRecorded), pBuffer, dwSamples);

        pwh->dwBytesRecorded += ulBytesCopied;
        dwWaveBufferLen -= ulBytesCopied;
        pBuffer += (ulBytesCopied/4);
        dwTotalBytes += (ulBytesCopied/4);
    }
    return dwTotalBytes;
}

// -----------------------------------------------------------------------------
//                      TransmitPackets
// -----------------------------------------------------------------------------
//  Takes data from wavebuffers and invokes DataPacketDown
// return: number of packets successfully sent down
// -----------------------------------------------------------------------------
static DWORD
TransmitPackets(
    PWAVEHDR    pwh,
    DWORD       dwCount,
    PDWORD      pdwError
    )
{
    DWORD dwDataBytes;
    DWORD dwPacketCount;
    int ret;

    *pdwError = ERROR_SUCCESS;

	//DEBUGMSG(1, (_T("=== BT Audio Driver Module: TransmitPackets. Count=%d. GetTickCount=%u. ===\n"), dwCount, GetTickCount()));

    for (dwPacketCount = 0; dwPacketCount < dwCount; dwPacketCount++)
    {
        dwDataBytes = ExtractFromWaveBuffers (pwh, g_pTxBuffer, g_dwScoPacketSize);
        if (dwDataBytes < g_dwScoPacketSize) {
            //BSS_ERRMSG2(L"=== BT Audio Driver Module: TransmitPackets (SILENCE). Bytes=%d. GetTickCount=%u. ===\n", g_dwScoPacketSize - dwDataBytes, GetTickCount());
            memset(g_pTxBuffer + dwDataBytes, SILENCE, g_dwScoPacketSize - dwDataBytes);
        }
        
        ret = g_ScoIntf.DataPacketDown (NULL, g_usScoConnHandle, g_pTxBuffer, g_dwScoPacketSize);
        if (ret) {
            *pdwError = ret;
            return dwPacketCount;
        }
    }

    return dwPacketCount;
}

	
// -----------------------------------------------------------------------------
//                      AudioThreadProc
// -----------------------------------------------------------------------------
//  This is the thread which waits for and processes SCO events.
// -----------------------------------------------------------------------------
DWORD AudioThreadProc(LPVOID lpParameter)
{
    int i;
    DWORD dwWaitRet;
    DWORD dwEvent;
    HANDLE hEvents[NUM_AUDIO_EVENTS];
    BOOL fAbort = FALSE;
    BOOL bSwapped = FALSE;
    HANDLE hTemp;

	// Set thread priority higher so audio experience is good
	// when system is busy
	HANDLE hCurThread = (HANDLE) GetCurrentThreadId();
	CeSetThreadPriority(hCurThread, DEFAULT_THREAD_PRIORITY);

    for (i = 0; i < NUM_AUDIO_EVENTS; i++)
    {
        hEvents[i] = g_hAudioEvents[i];
    }

    //
    // to access the gsi[apidir].pwh, need to set access key
    //
    DWORD dwAccessKey = GetCurrentPermissions();
    SetProcPermissions((ULONG) -1); //  access everybody

    BSS_VERBOSE("AudioThreadProc ready");

    while (1)
    {
        // documentation says that
        //   --WaitForMultipleObjects:
        //   ---If more than one object became signaled during the call, array index of the signaled object with 
        //   ---the smallest index value of all the signaled objects is returned.
        // since we want AUDIO_EVENT_RX_DATA and AUDIO_EVENT_TX_DATA to be treated fairly (equally)
        // we will swap those 2 event handles every time we call WaitForMultipleObjects
        //

        // swap the RX/TX event handles
        hTemp = hEvents[AUDIO_EVENT_RX_DATA];
        hEvents[AUDIO_EVENT_RX_DATA] = hEvents[AUDIO_EVENT_TX_DATA];
        hEvents[AUDIO_EVENT_TX_DATA] = hTemp;
        bSwapped = !bSwapped;

        dwWaitRet = WaitForMultipleObjects(NUM_AUDIO_EVENTS, hEvents, FALSE, INFINITE);
		if ( (dwWaitRet < WAIT_OBJECT_0) || (dwWaitRet >= (WAIT_OBJECT_0 + NUM_AUDIO_EVENTS)) ) {
            BSS_ERRMSG2("AudioThreadProc: WaitForMultipleObjects returned %#x, error %d", dwWaitRet, GetLastError());
            DeinitSco();
            return FALSE;
        }
        dwEvent = dwWaitRet - WAIT_OBJECT_0;

        // index corresponds to event unless it was an RX/TX event and things were swapped
        if (bSwapped && (dwEvent == AUDIO_EVENT_RX_DATA)) {
            dwEvent = AUDIO_EVENT_TX_DATA;
        } else if (bSwapped && (dwEvent == AUDIO_EVENT_TX_DATA)) {
            dwEvent = AUDIO_EVENT_RX_DATA;
        }

        if (dwEvent == AUDIO_EVENT_EXIT_THREAD) {
            BSS_INTMSG("AudioThreadProc : AUDIO_EVENT_EXIT_THREAD");
            DeinitSco();
            break;
        }

        switch (dwEvent)
        {
            case AUDIO_EVENT_RX_DATA:
                //BSS_INTMSG("AudioThreadProc : AUDIO_EVENT_RX_DATA");

                LOCK_STREAM_INFO(WAPI_IN);

                if (g_StreamInfo[WAPI_IN].bOpened && g_StreamInfo[WAPI_IN].bStarted) 
                {
                	UNLOCK_STREAM_INFO(WAPI_IN);
                	
                    LOCK_GSI(WAPI_IN);

                    LOCK_RXBUFFER();
                    BSS_VERBOSE1("AudioThreadProc : RxBufferToWaveBuffers g_dwRxBufferLen=%d", g_dwRxBufferLen);
                    RxBufferToWaveBuffers(gsi[WAPI_IN].pwh);
                    UNLOCK_RXBUFFER();

                    MarkFullAsDone(WAPI_IN);
                    RemoveCompleteBlocks(WAPI_IN);

                    UNLOCK_GSI(WAPI_IN);
                }
                else {
                	UNLOCK_STREAM_INFO(WAPI_IN);
                }
                
                break;

            case AUDIO_EVENT_TX_DATA:
                //BSS_INTMSG("AudioThreadProc : AUDIO_EVENT_TX_DATA");

                LOCK_STREAM_INFO(WAPI_OUT);

                if (g_StreamInfo[WAPI_OUT].bOpened && g_StreamInfo[WAPI_OUT].bStarted) 
                {
                    BOOL bSuccess;
                    DWORD dwError;

                    UNLOCK_STREAM_INFO(WAPI_OUT);

                    LOCK_GSI(WAPI_OUT);

                    LOCK_TXBUFFER();

                    BSS_VERBOSE1("AudioThreadProc : TransmitPackets num=%d", g_dwTxPacketsToSend);
                    bSuccess = ( g_dwTxPacketsToSend == TransmitPackets(gsi[WAPI_OUT].pwh, g_dwTxPacketsToSend, &dwError) );
                    g_dwTxPacketsToSend = 0;

                    UNLOCK_TXBUFFER();

                    if (bSuccess) {
                        MarkFullAsDone(WAPI_OUT);
                        RemoveCompleteBlocks(WAPI_OUT);
                    } else {
                        BSS_ERRMSG1("AudioThreadProc : error %d while transmitting packets", dwError);
                        fAbort = TRUE;
                    }

                    UNLOCK_GSI(WAPI_OUT);
                }
                else {
                	UNLOCK_STREAM_INFO(WAPI_OUT);
                }
                
                break;

            case AUDIO_EVENT_STACK_DOWN:
           	case AUDIO_EVENT_SCO_LINK_DISCONNECT:
                BSS_INTMSG("AudioThreadProc : AUDIO_EVENT_STACK_DOWN or AUDIO_EVENT_SCO_LINK_DISCONNECT");
                fAbort = TRUE;
                break;

            case AUDIO_EVENT_STACK_UP:
                BSS_INTMSG("AudioThreadProc : AUDIO_EVENT_STACK_UP");
                break;

        }

        if (fAbort) {
            wdev_WODM_RESET(0, 0, 0, 0);
            wdev_WIDM_RESET(0, 0, 0, 0);
            wdev_COMMON_CLOSE(WAPI_OUT, 0, 0, 0, 0);
            wdev_COMMON_CLOSE(WAPI_IN, 0, 0, 0, 0);

            DeinitSco();
            break;
        }
    }

    // change permission back
    SetProcPermissions(dwAccessKey);

    return TRUE;
}


// -----------------------------------------------------------------------------
//                          PddMsg_GetDevCaps
// -----------------------------------------------------------------------------
static MMRESULT
PddMsg_GetDevCaps(
    WAPI_INOUT apidir,
    PVOID pCaps,
    UINT  wSize
    )
{
    PWAVEINCAPS pwic  = (PWAVEINCAPS)pCaps;
    PWAVEOUTCAPS pwoc = (PWAVEOUTCAPS)pCaps;

    MMRESULT mmRet = MMSYSERR_NOERROR;

    BSS_FUNC_WPDD("+PddMsg_GetDevCaps");

    if (!pCaps) {
        return MMSYSERR_NOERROR;
    }

    pwoc->wMid = MM_MICROSOFT;
    pwoc->vDriverVersion = 0x0001;

    wsprintf (pwoc->szPname, TEXT("WinCE Bluetooth SCO Audio"));
    
    pwoc->wChannels = 1;

    if (apidir == WAPI_OUT) 
    {
        pwoc->wPid = 24;
        pwoc->wChannels = 2;
        pwoc->dwFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_1S16 | WAVE_FORMAT_2S16 | WAVE_FORMAT_4S16;

        // Caution: the WAVEINCAPS structure doesn't have a dwSupport field.
        pwoc->dwSupport = 0;
    }
    else {
        pwoc->wPid = 23;
        pwoc->wChannels = 1;
        pwoc->dwFormats = WAVE_FORMAT_1M08;
    }

    BSS_FUNC_WPDD("-PddMsg_GetDevCaps");

    return mmRet;
}


// -----------------------------------------------------------------------------
//                          PddMsg_Start
// -----------------------------------------------------------------------------
static MMRESULT
PddMsg_Start (
    WAPI_INOUT apidir,
    PWAVEHDR pwh
    )
{
    BSS_FUNC_WPDD("+PddMsg_Start");

    LOCK_STREAM_INFO(apidir);
    g_StreamInfo[apidir].bStarted = TRUE;
    UNLOCK_STREAM_INFO(apidir);

    LOCK_TXBUFFER();
    g_dwTxPacketsToSend = g_dwConcurrentPackets / 2;
    UNLOCK_TXBUFFER();

    if (apidir == WAPI_OUT) {
        // kick start packet transmission
        SetEvent(g_hAudioEvents[AUDIO_EVENT_TX_DATA]);
    }

    BSS_FUNC_WPDD("-PddMsg_Start");

    return MMSYSERR_NOERROR;
}


// -----------------------------------------------------------------------------
//                          PddMsg_Stop
// -----------------------------------------------------------------------------
static MMRESULT 
PddMsg_Stop(
    WAPI_INOUT apidir
    )
{
    BSS_FUNC_WPDD("+PddMsg_Stop");

    LOCK_STREAM_INFO(apidir);
    g_StreamInfo[apidir].bStarted = FALSE;
    UNLOCK_STREAM_INFO(apidir);

    BSS_FUNC_WPDD("-PddMsg_Stop");

    return MMSYSERR_NOERROR;
}


static DWORD
EstablishScoConnection(
    USHORT  *pusScoConnection
    )
{
    if (g_bConnectOut) {
        int iErr;

        //
        // get a list of all the current connections

⌨️ 快捷键说明

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