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

📄 wavepdd.cxx

📁 Windows CE操作系统中适用的蓝牙驱动程序
💻 CXX
📖 第 1 页 / 共 4 页
字号:
        //
        SCO_USER_CALL sucGetConns;
        BASEBAND_CONNECTION_DATA ConnData[MAX_BASEBAND_CONNECTIONS];
        memset(&sucGetConns, 0, sizeof(SCO_USER_CALL));
        sucGetConns.dwUserCallType = UCT_IOCTL_GET_BASEBAND_CONNECTIONS;
        sucGetConns.uParameters.IoctlGetBasebandConnections.dwCount = MAX_BASEBAND_CONNECTIONS;
        sucGetConns.uParameters.IoctlGetBasebandConnections.pConnections = ConnData;
        iErr = g_ScoIntf.Call(&sucGetConns);
        if (iErr) {
            BSS_ERRMSG1("UCT_IOCTL_GET_BASEBAND_CONNECTIONS failed %d", iErr);
            return iErr;
        }

        //
        // find the ACL connection to the remote device
        //
        BASEBAND_CONNECTION_DATA *pTargetData = NULL;
        DWORD dw;
        for (dw = 0; dw < sucGetConns.uParameters.IoctlGetBasebandConnections.dwCount; dw++)
        {
            if ( (ConnData[dw].baAddress == g_bdAddressOut) && (ConnData[dw].fLinkType == BT_LINK_TYPE_ACL) ) {
                pTargetData = &ConnData[dw];
                break;
            }
        }
        if (!pTargetData) {
            BSS_ERRMSG2("ACL connection to target address %04x%08x not found", g_bdAddressOut.NAP, g_bdAddressOut.SAP);
            return ERROR_CONNECTION_INVALID;
        }

        // dump baseband connection list
        for (dw = 0; dw < sucGetConns.uParameters.IoctlGetBasebandConnections.dwCount; dw++)
        {
            BSS_MISC4("h=%#x, ba=%04x%08x, type=%d", 
                    ConnData[dw].hConnection, 
                    ConnData[dw].baAddress.NAP, ConnData[dw].baAddress.SAP, 
                    ConnData[dw].fLinkType);
        }

        //
        // make a SCO connection to that device
        //
        SCO_USER_CALL sucConnect;
        memset(&sucConnect, 0, sizeof(SCO_USER_CALL));
        sucConnect.dwUserCallType = UCT_CONNECT;
        sucConnect.uParameters.Connect.hAclConnection = pTargetData->hConnection;
        iErr = g_ScoIntf.Call(&sucConnect);
        if (iErr) {
            BSS_ERRMSG1("Call UCT_CONNECT failed %d", iErr);
            return iErr;
        }

        *pusScoConnection = sucConnect.uParameters.Connect.hScoConnection;

        BSS_MISC3("Connection h=%#x to %04x%08x", *pusScoConnection, g_bdAddressOut.NAP, g_bdAddressOut.SAP);

    } else {

        int iErr;
        HANDLE hEvent;
        DWORD dwWaitRet;
        SCO_USER_CALL sucRecvConn;

        hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (!hEvent) {
            return GetLastError();
        }

        // setup parameters
        memset(&sucRecvConn, 0, sizeof(SCO_USER_CALL));
        sucRecvConn.dwUserCallType = UCT_RECV_CONNECTION;
        sucRecvConn.hEvent = hEvent;
        if (g_bdAddressIn.NAP || g_bdAddressIn.SAP) {
            sucRecvConn.uParameters.RecvConnection.bAllAddresses = FALSE;
            memcpy(&sucRecvConn.uParameters.RecvConnection.Address, &g_bdAddressIn, sizeof(BD_ADDR));
        } else {
            sucRecvConn.uParameters.RecvConnection.bAllAddresses = TRUE;
        }

        // initiate call
        iErr = g_ScoIntf.Call(&sucRecvConn);
        if (iErr) {
            CloseHandle(hEvent);
            BSS_ERRMSG1("Call UCT_RECV_CONNECTION initiation failed %d", iErr);
            return iErr;
        }

        // wait for completion
        BSS_VERBOSE2("Waiting for Call UCT_RECV_CONNECTION (%#x) for %d ms", &sucRecvConn, g_dwConnectInTimeout);
        dwWaitRet = WaitForSingleObject(hEvent, g_dwConnectInTimeout);
        CloseHandle(hEvent);
        if (dwWaitRet == WAIT_OBJECT_0) {
            iErr = sucRecvConn.iResult;
            if (iErr) {
                BSS_ERRMSG1("Call UCT_RECV_CONNECTION completed failed %d", iErr);
                return iErr;
            }

            BSS_MISC3("Connection h=%#x recved from %04x%08x", 
                            sucRecvConn.uParameters.RecvConnection.hScoConnection,
                            sucRecvConn.uParameters.RecvConnection.Address.NAP, 
                            sucRecvConn.uParameters.RecvConnection.Address.SAP);

            *pusScoConnection = sucRecvConn.uParameters.RecvConnection.hScoConnection;

        } else {
            // timeout expired.
            BSS_ERRMSG("Call UCT_RECV_CONNECTION timeout");
            g_ScoIntf.AbortCall(&sucRecvConn);
            return ERROR_TIMEOUT;
        }
    }

    return ERROR_SUCCESS;
}

//
// reads registry settings
//
// return FALSE : contains invalid information that cannot be ignored/defaulted
// return TRUE : otherwise
//
BOOL ReadRegistrySettings()
{
    LPCWSTR lpSubKey = L"SOFTWARE\\Microsoft\\Bluetooth\\AudioGateway\\Devices\\1";
	HKEY    hk;
    BOOL    bConnectOut = FALSE;
    BOOL    bConnectIn  = FALSE;

    // defaults

    g_dwAirCoding         = VS_AIR_CODING_CVSD;
    g_dwConnectInTimeout  = DEFAULT_SCO_CONNECT_IN_TIMEOUT;
    g_bConnectOut         = TRUE;
    g_fSigned             = FALSE;
    memset(&g_bdAddressIn, 0, sizeof(g_bdAddressIn));
    memset(&g_bdAddressOut, 0, sizeof(g_bdAddressOut));

	if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, lpSubKey, 0, KEY_READ, &hk) == ERROR_SUCCESS) {
        BT_ADDR btaddr;
		DWORD dwType = 0;
		DWORD dwData = 0;
        DWORD dwSize;

		dwSize = sizeof(dwData);
		if ((RegQueryValueEx (hk, L"AirCoding", NULL, &dwType, (LPBYTE)&dwData, &dwSize) == ERROR_SUCCESS) &&
            (dwType == REG_DWORD) && (dwSize == sizeof(dwData))) {
            if (    (dwData == VS_AIR_CODING_CVSD)
                ||  (dwData == VS_AIR_CODING_ULAW)
                ||  (dwData == VS_AIR_CODING_ALAW) ) {
                g_dwAirCoding = dwData;
            }
        }

		dwSize = sizeof(dwData);
		if ((RegQueryValueEx (hk, L"Direction", NULL, &dwType, (LPBYTE)&dwData, &dwSize) == ERROR_SUCCESS) &&
            (dwType == REG_DWORD) && (dwSize == sizeof(dwData))) {
            if (dwData) {
                bConnectIn  = TRUE;
            } else {
                bConnectOut = TRUE;
            }
        }

		dwSize = sizeof(dwData);
		if ((RegQueryValueEx (hk, L"ConnectInTimeout", NULL, &dwType, (LPBYTE)&dwData, &dwSize) == ERROR_SUCCESS) &&
            (dwType == REG_DWORD) && (dwSize == sizeof(dwData))) {
            g_dwConnectInTimeout = dwData;
        }

		dwSize = sizeof(BT_ADDR);
		if ((RegQueryValueEx (hk, L"AddressIn", NULL, &dwType, (LPBYTE)&btaddr, &dwSize) == ERROR_SUCCESS) &&
            (dwType == REG_BINARY)) {
			memcpy(&g_bdAddressIn, &btaddr, sizeof(BD_ADDR));
        }

		dwSize = sizeof(BT_ADDR);
		if ((RegQueryValueEx (hk, L"Address", NULL, &dwType, (LPBYTE)&btaddr, &dwSize) == ERROR_SUCCESS) &&
            (dwType == REG_BINARY)) {
			memcpy(&g_bdAddressOut, &btaddr, sizeof(BD_ADDR));
        }

		dwSize = sizeof(DWORD);
		if ((RegQueryValueEx (hk, L"8BitSignedSamples", NULL, &dwType, (LPBYTE)&dwData, &dwSize) == ERROR_SUCCESS) &&
            (dwType == REG_DWORD) && (dwSize == sizeof(dwData))) {
            g_fSigned = dwData;
        }

		RegCloseKey (hk);
	}

    if (!bConnectOut && !bConnectIn) {
        return FALSE;
    }

    if (bConnectOut) {
        g_bConnectOut = TRUE;
    } else {
        g_bConnectOut = FALSE;
    }

    return TRUE;
}

int InitSco()
{
	DWORD			dwRetVal = ERROR_SUCCESS;
	HANDLE			hThread;
	int				i;
	SCO_USER_CALL 	sucGetScoParams;
	SCO_USER_CALL	sucReadSetting;
	SCO_USER_CALL 	sucWriteSetting;
	VOICE_SETTING	setting;	

    if (g_fInitSco) {
    	// SCO has already been initialized.
        return ERROR_SUCCESS;
    }

    EnterCriticalSection(&g_csPddWaveProcLock);

    g_dwRxBufferLen     = 0;
    g_dwRxBufferStart   = 0;
    g_dwTxPacketsToSend = 0;
    g_dwScoPacketSize   = 0;
    g_usScoConnHandle   = 0;
    g_pTxBuffer			= NULL;

    if (!ReadRegistrySettings()) {
        BSS_ERRMSG("Invalid registry values");
        dwRetVal = ERROR_BADKEY;
        goto exit;
    }

    //
    // ensure SCO is supported and get number of SCO packets transport (e.g. USB) 
    // can support and size of packet
    //

    memset(&sucGetScoParams, 0, sizeof(SCO_USER_CALL));
    sucGetScoParams.dwUserCallType = UCT_IOCTL_GET_SCO_PARAMETERS;
    
    dwRetVal = g_ScoIntf.Call(&sucGetScoParams);
    if (dwRetVal) {
        BSS_ERRMSG1("SCO ioctl UCT_IOCTL_GET_SCO_PARAMETERS failed %d", dwRetVal);
        goto exit;
    }
    if ((!sucGetScoParams.uParameters.IoctlGetScoParameters.bScoSupported) ||
        (sucGetScoParams.uParameters.IoctlGetScoParameters.dwNumConcurrentScoPackets == 0) ||
        (sucGetScoParams.uParameters.IoctlGetScoParameters.dwScoPacketMaxDataSize == 0)
       ) {
        BSS_ERRMSG("SCO not supported or bad return values");
        dwRetVal = ERROR_NOT_SUPPORTED;
        goto exit;
    }
    g_dwConcurrentPackets = sucGetScoParams.uParameters.IoctlGetScoParameters.dwNumConcurrentScoPackets;
    g_dwScoPacketSize = sucGetScoParams.uParameters.IoctlGetScoParameters.dwScoPacketMaxDataSize;

    //
    // read the device voice setting
    //
    
    memset(&sucReadSetting, 0, sizeof(sucReadSetting));
    sucReadSetting.dwUserCallType = UCT_READ_VOICE_SETTING;
    
    dwRetVal = g_ScoIntf.Call(&sucReadSetting);
    if (dwRetVal) {
        BSS_ERRMSG1("Call UCT_READ_VOICE_SETTING failed %d", dwRetVal);
        goto exit;
    }
    setting = sucReadSetting.uParameters.ReadVoiceSetting.VoiceSetting;

    //
    // write a new voice setting
    //
    
    memset(&sucWriteSetting, 0, sizeof(SCO_USER_CALL));
    sucWriteSetting.dwUserCallType 	    = UCT_WRITE_VOICE_SETTING;
    setting.Parameters.fAirCoding       = g_dwAirCoding;
    setting.Parameters.fInputSampleSize = VS_INPUT_SAMPLE_SIZE_8BIT;
    sucWriteSetting.uParameters.WriteVoiceSetting.VoiceSetting = setting;
    
    dwRetVal = g_ScoIntf.Call(&sucWriteSetting);
    if (dwRetVal) {
        BSS_ERRMSG1("Call UCT_WRITE_VOICE_SETTING failed %d", dwRetVal);
        goto exit;
    }

	//
	// Allocate Transmit buffer
	// 

	if (g_dwScoPacketSize > TX_BUFFER_SIZE) {
		g_pTxBuffer =  (UCHAR*) LocalAlloc(0, g_dwScoPacketSize);
		if (! g_pTxBuffer) {
			goto exit;
		}
	}
	else {
		g_pTxBuffer = g_TxBuffer;
	}

    //
    // establish the SCO connection
    //
    
    dwRetVal = EstablishScoConnection(&g_usScoConnHandle);
    if (dwRetVal) {
        BSS_ERRMSG1("EstablishScoConnection FAILED %d", dwRetVal);
        goto exit;
    }

    BSS_VERBOSE1("SCO connection established h=%#x", g_usScoConnHandle);

	// Reset Events
	for (i = 0; i < NUM_AUDIO_EVENTS; i++) {
        ResetEvent(g_hAudioEvents[i]);        
    }

    //
    // create the thread that handles SCO events
    //
    
    hThread = CreateThread(NULL, 0, AudioThreadProc, NULL, 0, NULL);
    if (! hThread) {
        DWORD err = GetLastError();
        BSS_ERRMSG("CreateThread FAILED");
        goto exit;
    }    
    
    CloseHandle(hThread);

	g_fInitSco = TRUE;

exit:
	LeaveCriticalSection(&g_csPddWaveProcLock);
	
	if (! g_fInitSco) {
		DeinitSco();
	}
	
    return dwRetVal;
}

int DeinitSco(void)
{
    if (g_usScoConnHandle) {
        SCO_USER_CALL sucDisconnect = {0};
        sucDisconnect.dwUserCallType = UCT_DISCONNECT;
        sucDisconnect.uParameters.Disconnect.hScoConnection = g_usScoConnHandle;
        USHORT usTemp = g_usScoConnHandle;
        g_usScoConnHandle = 0;
        int iErr = g_ScoIntf.Call(&sucDisconnect);
        if (iErr) {
            BSS_ERRMSG2("DeinitSco : Call UCT_DISCONNECT (h=%#x) failed %d\n", usTemp, iErr);
        }
    }

    if (g_pTxBuffer && (g_pTxBuffer != g_TxBuffer)) {
    	LocalFree(g_pTxBuffer);
    	g_pTxBuffer = NULL;
    }

    g_dwRxBufferLen     = 0;
    g_dwRxBufferStart   = 0;
    g_dwTxPacketsToSend = 0;
    g_dwScoPacketSize   = 0;

    g_fInitSco = FALSE;

    return ERROR_SUCCESS;
}

// -----------------------------------------------------------------------------
//                          PddMsg_Open
// -----------------------------------------------------------------------------

⌨️ 快捷键说明

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