📄 audiogw.cpp
字号:
m_sockServer[0] = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
if (INVALID_SOCKET == m_sockServer[0]) {
DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Error opening socket: %d.\n", GetLastError()));
goto exit;
}
if (fHandsfree) {
m_sockServer[1] = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
if (INVALID_SOCKET == m_sockServer[1]) {
DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Error opening socket: %d.\n", GetLastError()));
goto exit;
}
}
// Bind headset socket and add SDP record
memset(&saServer, 0, sizeof(saServer));
saServer.addressFamily = AF_BTH;
if (0 != bind(m_sockServer[0], (SOCKADDR*)&saServer, sizeof(saServer))) {
DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Error calling bind: %d.\n", GetLastError()));
goto exit;
}
iLen = sizeof(saServer);
if (SOCKET_ERROR == getsockname(m_sockServer[0], (SOCKADDR*)&saServer, &iLen)) {
DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Error calling getsockname: %d.\n", GetLastError()));
goto exit;
}
if (ERROR_SUCCESS != AddSDPRecord(rgbSdpRecordHeadsetHS, SDP_HS_RECORD_SIZE, SDP_HS_CHANNEL_OFFSET, saServer.port, &m_SDPRecordHS)) {
DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Error adding headset SDP record.\n"));
goto exit;
}
// Bind hands-free socket and add SDP record
if (fHandsfree) {
memset(&saServer, 0, sizeof(saServer));
saServer.addressFamily = AF_BTH;
if (0 != bind(m_sockServer[1], (SOCKADDR*)&saServer, sizeof(saServer))) {
DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Error calling bind: %d.\n", GetLastError()));
goto exit;
}
iLen = sizeof(saServer);
if (SOCKET_ERROR == getsockname(m_sockServer[1], (SOCKADDR*)&saServer, &iLen)) {
DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Error calling getsockname: %d.\n", GetLastError()));
goto exit;
}
rgbSdpRecordHeadsetHF[SDP_HF_CAPABILITY_OFFSET] = (BYTE) AGProps.usHFCapability;
if (ERROR_SUCCESS != AddSDPRecord(rgbSdpRecordHeadsetHF, SDP_HF_RECORD_SIZE, SDP_HF_CHANNEL_OFFSET, saServer.port, &m_SDPRecordHF)) {
DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Error adding hands-free SDP record.\n"));
goto exit;
}
}
// Continue setting up sockets
listen(m_sockServer[0], 2);
if (fHandsfree) {
listen(m_sockServer[1], 2);
}
m_AGEngine.GetAGProps(&AGProps);
if (AGProps.fAuth) {
DEBUGMSG(ZONE_SERVICE, (L"BTAGSVC: Setting SO_BTH_AUTHENTICATE on server socket.\n"));
setsockopt(m_sockServer[0], SOL_RFCOMM, SO_BTH_AUTHENTICATE, (char *)&on, sizeof(on));
if (fHandsfree) {
setsockopt(m_sockServer[1], SOL_RFCOMM, SO_BTH_AUTHENTICATE, (char *)&on, sizeof(on));
}
}
if (AGProps.fEncrypt) {
DEBUGMSG(ZONE_SERVICE, (L"BTAGSVC: Setting SO_BTH_ENCRYPT on server socket.\n"));
setsockopt(m_sockServer[0], SOL_RFCOMM, SO_BTH_ENCRYPT, (char *)&on, sizeof(on));
if (fHandsfree) {
setsockopt(m_sockServer[1], SOL_RFCOMM, SO_BTH_ENCRYPT, (char *)&on, sizeof(on));
}
}
while (1) {
SOCKADDR_BTH saClient;
SOCKET sockClient;
BOOL fHFSupport = FALSE;
fd_set sockSet;
FD_ZERO(&sockSet);
FD_SET(m_sockServer[0], &sockSet);
if (fHandsfree) {
FD_SET(m_sockServer[1], &sockSet);
}
Unlock();
int iSockets = select(0,&sockSet,NULL,NULL,NULL);
Lock();
if (m_fShutdown || (0 == iSockets) || (SOCKET_ERROR == iSockets)) {
DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Error in call to select: %d\n", GetLastError()));
goto exit;
}
SOCKET s = sockSet.fd_array[iSockets - 1];
if (fHandsfree && (s == m_sockServer[1])) {
// Peer device supports HFP
fHFSupport = TRUE;
}
iLen = sizeof(saClient);
sockClient = accept(s, (SOCKADDR*)&saClient, &iLen);
if (INVALID_SOCKET == sockClient) {
DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Error in call to accept, breaking... - error:%d\n", GetLastError()));
goto exit;
}
DEBUGMSG(ZONE_SERVICE, (L"BTAGSVC: A Bluetooth peer device has connected to the Audio Gateway.\n"));
if (!m_AGEngine.FindBTAddrInList(saClient.btAddr)) {
DEBUGMSG(ZONE_WARN, (L"BTAGSVC: The peer device was not accepted since the user has never confirmed it as a device to be used.\n"));
closesocket(sockClient);
continue;
}
m_AGEngine.GetAGProps(&AGProps);
if (AGProps.btAddrClient && (AGProps.btAddrClient != saClient.btAddr)) {
DEBUGMSG(ZONE_WARN, (L"BTAGSVC: The peer device was not accepted since we already have an active connection.\n"));
closesocket(sockClient);
continue;
}
(void) m_AGEngine.SetBTAddrList(saClient.btAddr, fHFSupport); // ignore return value in this case
if (ERROR_SUCCESS != m_AGEngine.NotifyConnect(sockClient, fHFSupport)) {
DEBUGMSG(ZONE_WARN, (L"BTAGSVC: The AG Engine did not accept the connection to the device.\n"));
closesocket(sockClient);
continue;
}
}
exit:
if (m_SDPRecordHF) {
RemoveSDPRecord(&m_SDPRecordHF);
}
if (m_SDPRecordHS) {
RemoveSDPRecord(&m_SDPRecordHS);
}
g_dwState = SERVICE_STATE_OFF;
Unlock();
if (! m_fShutdown) {
Stop();
}
DEBUGMSG(ZONE_SERVICE, (L"BTAGSVC: --ListenThread_Int\n"));
}
// AG SCO Server Thread
DWORD WINAPI CAGService::SCOListenThread(LPVOID pv)
{
CAGService* pInst = (CAGService*)pv;
pInst->SCOListenThread_Int();
return 0;
}
// This method listens for incoming SCO connections to the AG
void CAGService::SCOListenThread_Int(void)
{
DWORD dwErr = ERROR_SUCCESS;
AG_PROPS AGProps;
DEBUGMSG(ZONE_SERVICE, (L"BTAGSVC: ++SCOListenThread_Int\n"));
Lock();
m_AGEngine.GetAGProps(&AGProps);
if (AGProps.fPCMMode) {
dwErr = BthAcceptSCOConnections(TRUE);
}
if (ERROR_SUCCESS == dwErr) {
HANDLE hBTConnect = OpenEvent(EVENT_ALL_ACCESS, FALSE, L"system/events/bluetooth/ConnectionsChange");
if (hBTConnect) {
HANDLE h[2];
DWORD dwWait;
h[0] = hBTConnect;
h[1] = m_hCloseEvent;
while (1) {
Unlock();
dwWait = WaitForMultipleObjects(2, h, FALSE, INFINITE);
Lock();
if (dwWait != WAIT_OBJECT_0) {
break;
}
DEBUGMSG(ZONE_SERVICE, (L"BTAGSVC: SCOListenThread_Int - Connection Event.\n"));
m_AGEngine.ConnectionEvent();
}
}
else {
DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: SCOListenThread_Int: Error opening named event: %d\n", dwErr));
}
if (AGProps.fPCMMode) {
BthAcceptSCOConnections(FALSE);
}
}
else {
DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: SCOListenThread_Int: Error accepting SCO connections: %d\n", dwErr));
}
Unlock();
DEBUGMSG(ZONE_SERVICE, (L"BTAGSVC: --SCOListenThread_Int\n"));
}
// This method loads AG settings
DWORD CAGService::LoadAGState(void)
{
DWORD dwRetVal = ERROR_SUCCESS;
DWORD cdwBytes = 0;
DWORD dwData = 0;
HKEY hk = NULL;
AG_PROPS AGProps;
m_AGEngine.GetAGProps(&AGProps);
dwRetVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE, RK_AUDIO_GATEWAY, 0, 0, &hk);
if (dwRetVal != ERROR_SUCCESS) {
goto exit;
}
cdwBytes = sizeof(dwData);
if (ERROR_SUCCESS == RegQueryValueEx(hk, _T("MapAudioToPcmMode"), 0, NULL, (PBYTE)&dwData, &cdwBytes)) {
AGProps.fPCMMode = dwData;
}
cdwBytes = sizeof(dwData);
if (ERROR_SUCCESS == RegQueryValueEx(hk, _T("MicVolume"), 0, NULL, (PBYTE)&dwData, &cdwBytes)) {
AGProps.usMicVolume = (USHORT) dwData;
}
cdwBytes = sizeof(dwData);
if (ERROR_SUCCESS == RegQueryValueEx(hk, _T("SpkVolume"), 0, NULL, (PBYTE)&dwData, &cdwBytes)) {
AGProps.usSpeakerVolume = (USHORT) dwData;
}
cdwBytes = sizeof(dwData);
if (ERROR_SUCCESS == RegQueryValueEx(hk, _T("Authenticate"), 0, NULL, (PBYTE)&dwData, &cdwBytes)) {
AGProps.fAuth = dwData;
}
cdwBytes = sizeof(dwData);
if (ERROR_SUCCESS == RegQueryValueEx(hk, _T("Enrypt"), 0, NULL, (PBYTE)&dwData, &cdwBytes)) {
AGProps.fEncrypt = dwData;
}
cdwBytes = sizeof(dwData);
if (ERROR_SUCCESS == RegQueryValueEx(hk, _T("NoHandsfree"), 0, NULL, (PBYTE)&dwData, &cdwBytes)) {
AGProps.fNoHandsfree = dwData;
}
cdwBytes = sizeof(dwData);
if (ERROR_SUCCESS == RegQueryValueEx(hk, _T("PowerSave"), 0, NULL, (PBYTE)&dwData, &cdwBytes)) {
AGProps.fPowerSave = dwData;
}
cdwBytes = sizeof(dwData);
if (ERROR_SUCCESS == RegQueryValueEx(hk, _T("Capability"), 0, NULL, (PBYTE)&dwData, &cdwBytes)) {
AGProps.usHFCapability = (USHORT) dwData;
}
cdwBytes = sizeof(dwData);
if (ERROR_SUCCESS == RegQueryValueEx(hk, _T("PageTimeout"), 0, NULL, (PBYTE)&dwData, &cdwBytes)) {
AGProps.usPageTimeout = (USHORT) dwData;
}
cdwBytes = sizeof(dwData);
if (ERROR_SUCCESS == RegQueryValueEx(hk, _T("SniffDelay"), 0, NULL, (PBYTE)&dwData, &cdwBytes)) {
AGProps.ulSniffDelay = (ULONG) dwData;
}
cdwBytes = sizeof(dwData);
if (ERROR_SUCCESS == RegQueryValueEx(hk, _T("SniffMax"), 0, NULL, (PBYTE)&dwData, &cdwBytes)) {
AGProps.usSniffMax = (USHORT) dwData;
}
cdwBytes = sizeof(dwData);
if (ERROR_SUCCESS == RegQueryValueEx(hk, _T("SniffMin"), 0, NULL, (PBYTE)&dwData, &cdwBytes)) {
AGProps.usSniffMin = (USHORT) dwData;
}
cdwBytes = sizeof(dwData);
if (ERROR_SUCCESS == RegQueryValueEx(hk, _T("SniffAttempt"), 0, NULL, (PBYTE)&dwData, &cdwBytes)) {
AGProps.usSniffAttempt = (USHORT) dwData;
}
cdwBytes = sizeof(dwData);
if (ERROR_SUCCESS == RegQueryValueEx(hk, _T("SniffTimeout"), 0, NULL, (PBYTE)&dwData, &cdwBytes)) {
AGProps.usSniffTimeout = (USHORT) dwData;
}
RegCloseKey(hk);
m_AGEngine.SetAGProps(&AGProps);
exit:
return dwRetVal;
}
// This method saves AG settings
DWORD CAGService::SaveAGState(void)
{
DWORD dwRetVal = ERROR_SUCCESS;
DWORD dwDisp = 0;
DWORD dwData = 0;
HKEY hk = NULL;
AG_PROPS AGProps;
dwRetVal = RegCreateKeyEx(HKEY_LOCAL_MACHINE, RK_AUDIO_GATEWAY, 0, NULL, 0, NULL, NULL, &hk, &dwDisp);
if (ERROR_SUCCESS != dwRetVal) {
goto exit;
}
m_AGEngine.GetAGProps(&AGProps);
dwData = AGProps.usMicVolume;
dwRetVal = RegSetValueEx(hk, _T("MicVolume"), 0, REG_DWORD, (PBYTE)&dwData, sizeof(dwData));
if (ERROR_SUCCESS != dwRetVal) {
goto exit;
}
dwData = AGProps.usSpeakerVolume;
dwRetVal = RegSetValueEx(hk, _T("SpkVolume"), 0, REG_DWORD, (PBYTE)&dwData, sizeof(dwData));
if (ERROR_SUCCESS != dwRetVal) {
goto exit;
}
dwData = AGProps.fPowerSave;
dwRetVal = RegSetValueEx(hk, _T("PowerSave"), 0, REG_DWORD, (PBYTE)&dwData, sizeof(dwData));
if (ERROR_SUCCESS != dwRetVal) {
goto exit;
}
exit:
if (hk) {
RegCloseKey(hk);
}
return dwRetVal;
}
// This method adds an SDP record
DWORD CAGService::AddSDPRecord(PBYTE rbgSdpRecord, DWORD cbSdpRecord, DWORD dwChannelOffset, unsigned long ulPort, unsigned long* pSdpRecord)
{
DWORD dwRetVal = ERROR_SUCCESS;
DWORD dwSizeOut = 0;
struct {
BTHNS_SETBLOB b;
unsigned char uca[MAX_SDP_RECORD_SIZE];
} bigBlob;
ULONG ulSdpVersion = BTH_SDP_VERSION;
*pSdpRecord = 0;
bigBlob.b.pRecordHandle = pSdpRecord;
bigBlob.b.pSdpVersion = &ulSdpVersion;
bigBlob.b.fSecurity = 0;
bigBlob.b.fOptions = 0;
bigBlob.b.ulRecordLength = cbSdpRecord;
memcpy(bigBlob.b.pRecord, rbgSdpRecord, cbSdpRecord);
bigBlob.b.pRecord[dwChannelOffset] = (unsigned char)ulPort;
BLOB blob;
blob.cbSize = sizeof(BTHNS_SETBLOB) + cbSdpRecord - 1;
blob.pBlobData = (PBYTE) &bigBlob;
WSAQUERYSET Service;
memset(&Service, 0, sizeof(Service));
Service.dwSize = sizeof(Service);
Service.lpBlob = &blob;
Service.dwNameSpace = NS_BTH;
dwRetVal = WSASetService(&Service, RNRSERVICE_REGISTER, 0);
if (ERROR_SUCCESS != dwRetVal) {
DEBUGMSG(ZONE_ERROR, (L"BTAGSVC: Error adding SDP record.\n"));
goto exit;
}
DEBUGMSG(ZONE_SERVICE, (L"BTAGSVC: Successfully added SDP record.\n"));
exit:
return dwRetVal;
}
// This method removes an SDP record
DWORD CAGService::RemoveSDPRecord(unsigned long* pSdpRecord)
{
DWORD dwRetVal = ERROR_SUCCESS;
ULONG ulSdpVersion = BTH_SDP_VERSION;
BTHNS_SETBLOB delBlob;
memset(&delBlob, 0, sizeof(delBlob));
delBlob.pRecordHandle = pSdpRecord;
delBlob.pSdpVersion = &ulSdpVersion;
BLOB blob;
blob.cbSize = sizeof(BTHNS_SETBLOB);
blob.pBlobData = (PBYTE) &delBlob;
WSAQUERYSET Service;
memset(&Service, 0, sizeof(Service));
Service.dwSize = sizeof(Service);
Service.lpBlob = &blob;
Service.dwNameSpace = NS_BTH;
dwRetVal = WSASetService(&Service, RNRSERVICE_DELETE, 0);
*pSdpRecord = 0;
#ifdef DEBUG
if (ERROR_SUCCESS == dwRetVal) {
DEBUGMSG(ZONE_SERVICE, (L"BTAGSVC: Successfully removed SDP record.\n"));
}
#endif // DEBUG
return dwRetVal;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -