📄 wavepdd.cxx
字号:
//
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 + -