📄 hci.cxx
字号:
while (pRunner) {
SVSUTIL_ASSERT (pRunner != pPacket);
pRunner = pRunner->pNext;
}
pRunner = gpHCI->pPacketsPending;
while (pRunner) {
SVSUTIL_ASSERT (pRunner != pPacket);
pRunner = pRunner->pNext;
}
}
#endif
HCIPacket *pParent = NULL;
if (! pPacket) {
pPacket = gpHCI->pPackets;
pParent = NULL;
while (pPacket) {
if ((pPacket->pOwner == pDeviceContext) && (pPacket->pCallContext == pCallContext)) {
if (! pParent)
gpHCI->pPackets = pPacket->pNext;
else
pParent->pNext = pPacket->pNext;
IFDBG(DebugOut (DEBUG_HCI_PACKETS, L"RetireCall:: found not executed packet\n"));
break;
}
pParent = pPacket;
pPacket = pPacket->pNext;
}
}
if (! pPacket) {
pPacket = gpHCI->pPacketsPending;
pParent = NULL;
while (pPacket) {
if ((pPacket->pOwner == pDeviceContext) && (pPacket->pCallContext == pCallContext)) {
if (! pParent)
gpHCI->pPacketsPending = pPacket->pNext;
else
pParent->pNext = pPacket->pNext;
IFDBG(DebugOut (DEBUG_HCI_PACKETS, L"RetireCall:: found pending packet\n"));
break;
}
pParent = pPacket;
pPacket = pPacket->pNext;
}
}
if (! pPacket) {
pPacket = gpHCI->pPacketsSent;
pParent = NULL;
while (pPacket) {
if ((pPacket->pOwner == pDeviceContext) && (pPacket->pCallContext == pCallContext)) {
if (! pParent)
gpHCI->pPacketsSent = pPacket->pNext;
else
pParent->pNext = pPacket->pNext;
IFDBG(DebugOut (DEBUG_HCI_PACKETS, L"RetireCall:: found sent packet\n"));
break;
}
pParent = pPacket;
pPacket = pPacket->pNext;
}
}
if (! pPacket) {
IFDBG(DebugOut (DEBUG_HCI_PACKETS, L"RetireCall:: ERROR_NOT_FOUND\n"));
return ERROR_NOT_FOUND;
}
BT_LAYER_CALL_ABORTED pCallback = (pPacket->pOwner && VerifyContext (pPacket->pOwner)) ?
pPacket->pOwner->c.hci_CallAborted : NULL;
delete pPacket;
if (pCallback) {
gpHCI->AddRef ();
IFDBG(DebugOut (DEBUG_HCI_PACKETS, L"RetireCall:: going into callback\n"));
gpHCI->Unlock ();
__try {
pCallback (pCallContext, iError);
} __except (1) {
IFDBG(DebugOut (DEBUG_HCI_PACKETS, L"RetireCall:: exception in callback\n"));
}
gpHCI->Lock ();
IFDBG(DebugOut (DEBUG_HCI_PACKETS, L"RetireCall:: came from callback\n"));
gpHCI->Release ();
}
IFDBG(DebugOut (DEBUG_HCI_PACKETS, L"RetireCall:: ERROR_SUCCESS\n"));
return ERROR_SUCCESS;
}
// We don't use HCI transport offsets because data is copied anyway into the local buffer
static int FillBuffer (HCIPacket *pPacket, int cSize, unsigned char *lpBuffer) {
if (pPacket->ePacketType == DATA_PACKET_ACL) { // get the buffer
// MUST pB
int cTransfer = BufferTotal (pPacket->pContents);
SVSUTIL_ASSERT ((cTransfer <= 0xffff) && (cTransfer > 0));
if (cTransfer > gpHCI->sDeviceBuffer.ACL_Data_Packet_Length)
cTransfer = gpHCI->sDeviceBuffer.ACL_Data_Packet_Length;
if (cTransfer > cSize - 4)
cTransfer = cSize - 4;
*(unsigned short *)lpBuffer = pPacket->uPacket.DataPacketAcl.hConnection | ((pPacket->uPacket.DataPacketAcl.cCompleted ? 1 : 2) << 12);
lpBuffer += 2;
*(unsigned short *)lpBuffer = (unsigned short)cTransfer;
lpBuffer += 2;
int iRes = BufferGetChunk (pPacket->pContents, cTransfer, lpBuffer);
SVSUTIL_ASSERT (iRes);
pPacket->uPacket.DataPacketAcl.cCompleted += cTransfer;
++pPacket->uPacket.DataPacketAcl.cSubsPending;
return cTransfer + 4;
} else if (pPacket->ePacketType == DATA_PACKET_SCO) {
int cTransfer = pPacket->uPacket.DataPacketSco.cTotal;
int cMaxScoDataLen = gpHCI->sDeviceBuffer.SCO_Data_Packet_Length;
int cTransportDataLen = gpHCI->transport.iScoWritePacketSize - 3;
if ( (cTransportDataLen > 0) && (cTransportDataLen < cMaxScoDataLen) ) {
cMaxScoDataLen = cTransportDataLen;
}
SVSUTIL_ASSERT ((cTransfer <= 0xff) && (cTransfer > 0));
if (cTransfer > cMaxScoDataLen)
cTransfer = cMaxScoDataLen;
if (cTransfer > cSize - 3)
cTransfer = cSize - 3;
SVSUTIL_ASSERT ((cTransfer <= 0xff) && (cTransfer > 0));
*(unsigned short *)lpBuffer = pPacket->uPacket.DataPacketSco.hConnection;
lpBuffer += 2;
*lpBuffer++ = (unsigned char)cTransfer;
int iRes = BufferGetChunk (pPacket->pContents, cTransfer, lpBuffer);
SVSUTIL_ASSERT (iRes);
pPacket->uPacket.DataPacketAcl.cSubsPending = 1;
return cTransfer + 3;
}
SVSUTIL_ASSERT (pPacket->ePacketType == COMMAND_PACKET);
SVSUTIL_ASSERT (pPacket->pContents->cStart == 0);
SVSUTIL_ASSERT (pPacket->pContents->cEnd == pPacket->pContents->cSize);
SVSUTIL_ASSERT (pPacket->pContents->cSize >= 3);
SVSUTIL_ASSERT (pPacket->pContents->pBuffer[2] + 3 == BufferTotal (pPacket->pContents));
if (BufferTotal (pPacket->pContents) > cSize) {
SVSUTIL_ASSERT (0);
return 0;
}
memcpy (lpBuffer, pPacket->pContents->pBuffer + pPacket->pContents->cStart, BufferTotal (pPacket->pContents));
return BufferTotal (pPacket->pContents);
}
static DWORD WINAPI WriterThread (LPVOID lpvUnused) {
IFDBG(DebugOut (DEBUG_HCI_INIT, L"WT: Started\n"));
if (! gpHCI) {
IFDBG(DebugOut (DEBUG_ERROR, L"WT: Totally out of sync - exiting\n"));
return 0;
}
gpHCI->Lock ();
if (gpHCI->eStage != AlmostRunning) {
gpHCI->eStage = Error;
ShutdownTransport ();
IFDBG(DebugOut (DEBUG_ERROR, L"WT: Totally out of sync - exiting\n"));
gpHCI->Unlock ();
return 0;
}
HANDLE hEvent = gpHCI->hQueue;
BD_BUFFER bPacket;
bPacket.fMustCopy = TRUE;
bPacket.pFree = NULL;
bPacket.cSize = gpHCI->transport.iWriteBufferHeader + gpHCI->transport.iMaxSizeWrite + gpHCI->transport.iWriteBufferTrailer;
bPacket.pBuffer = (unsigned char *)g_funcAlloc (bPacket.cSize, g_pvAllocData);
if (! bPacket.pBuffer) {
gpHCI->eStage = Error;
ShutdownTransport ();
IFDBG(DebugOut (DEBUG_ERROR, L"WT: No memory!\n"));
gpHCI->Unlock ();
return 0;
}
DWORD dwScoSyncTimeOffset = 0xffffffff;
DWORD dwHciCommTimeout = gpHCI->transport.uiWriteTimeout;
gpHCI->Unlock ();
IFDBG(DebugOut (DEBUG_HCI_INIT, L"WT: Initialization complete - waiting for communications...\n"));
for ( ; ; ) {
#if defined (DEBUG) || defined (_DEBUG)
extern void L2CAPD_CheckLock (void);
L2CAPD_CheckLock ();
#endif
IFDBG(DebugOut (DEBUG_HCI_PACKETS, L"Writer: go to sleep\n"));
DWORD dwResult = WaitForSingleObject (hEvent, dwHciCommTimeout);
IFDBG(DebugOut (DEBUG_HCI_PACKETS, L"Writer: woke up\n"));
if ((dwResult != WAIT_OBJECT_0) && (dwResult != WAIT_TIMEOUT)) { // Can only be at shutdown
g_funcFree (bPacket.pBuffer, g_pvFreeData);
IFDBG(DebugOut (DEBUG_HCI_INIT, L"WT: Exiting - event closed at shutdown...\n"));
return 0;
}
if (! gpHCI) {
g_funcFree (bPacket.pBuffer, g_pvFreeData);
IFDBG(DebugOut (DEBUG_HCI_INIT, L"WT: Exiting - lost global state...\n"));
return 0;
}
gpHCI->Lock ();
if ((gpHCI->eStage != AlmostRunning) && (gpHCI->eStage != Connected)) {
g_funcFree (bPacket.pBuffer, g_pvFreeData);
IFDBG(DebugOut (DEBUG_HCI_INIT, L"WT: Exiting - shutting down...\n"));
gpHCI->Unlock ();
return 0;
}
DWORD dwCurrTime = GetTickCount ();
if ((dwScoSyncTimeOffset == 0xffffffff) && gpHCI->sDeviceBuffer.SCO_Data_Packet_Length) {
DWORD dwScoPacketSize = gpHCI->transport.iScoWritePacketSize - 3;
if (dwScoPacketSize > gpHCI->sDeviceBuffer.SCO_Data_Packet_Length)
dwScoPacketSize = gpHCI->sDeviceBuffer.SCO_Data_Packet_Length;
if (gpHCI->transport.iScoSampleSize)
dwScoSyncTimeOffset = (gpHCI->transport.iScoWriteNumPackets - gpHCI->transport.iScoWriteLowNumPackets) * (dwScoPacketSize / gpHCI->transport.iScoSampleSize);
}
if (((gpHCI->cCommandPacketsAllowed <= 0) || gpHCI->pPacketsSent) &&
((int)dwCurrTime - (int)gpHCI->dwCommandPacketTimeout > 0) &&
(gpHCI->eStage == Connected)
) {
gpHCI->eStage = Error;
ShutdownTransport ();
g_funcFree (bPacket.pBuffer, g_pvFreeData);
IFDBG(DebugOut (DEBUG_HCI_INIT, L"WT: Exiting - command packet timeout...\n"));
gpHCI->Unlock ();
return 0;
}
if (! gpHCI->pPackets) {
IFDBG(DebugOut (DEBUG_HCI_PACKETS, L"Writer : no packets\n"));
if (gpHCI->pPacketsSent || gpHCI->pPacketsPending)
dwHciCommTimeout = gpHCI->transport.uiWriteTimeout;
else
dwHciCommTimeout = INFINITE; // No activity
gpHCI->Unlock ();
continue;
}
if (((gpHCI->cCommandPacketsAllowed <= 0) || gpHCI->pPacketsSent) && (gpHCI->eStage == Connected))
dwHciCommTimeout = gpHCI->dwCommandPacketTimeout - dwCurrTime;
else
dwHciCommTimeout = gpHCI->transport.uiWriteTimeout;
HCIPacket *pPacket = gpHCI->pPackets;
HCIPacket *pParent = NULL;
while (pPacket) { // Send the packet
if ((pPacket->ePacketType == COMMAND_PACKET) && (gpHCI->cCommandPacketsAllowed > 0)) {
--gpHCI->cCommandPacketsAllowed;
gpHCI->dwCommandPacketTimeout = dwCurrTime + gpHCI->transport.uiWriteTimeout;
break;
} else if ((pPacket->ePacketType == DATA_PACKET_ACL) || (pPacket->ePacketType == DATA_PACKET_SCO)) {
BasebandConnection *pC = FindConnection (pPacket->uPacket.DataPacketU.hConnection);
if (! pC) { // Stale, unlink
if (pParent)
pParent->pNext = pPacket->pNext;
else
gpHCI->pPackets = pPacket->pNext;
RetireCall (pPacket, pPacket->pOwner, pPacket->pCallContext, ERROR_CONNECTION_ABORTED);
if ((gpHCI->eStage != AlmostRunning) && (gpHCI->eStage != Connected)) {
g_funcFree (bPacket.pBuffer, g_pvFreeData);
gpHCI->Unlock ();
return 0;
}
pPacket = gpHCI->pPackets;
pParent = NULL;
continue;
}
if ((pPacket->ePacketType == DATA_PACKET_ACL) && (gpHCI->cTotalAclDataPacketsPending < gpHCI->sDeviceBuffer.Total_Num_ACL_Data_Packets)) {
++pC->cAclDataPacketsPending; // per connection
++gpHCI->cTotalAclDataPacketsPending;
break;
}
if (pPacket->ePacketType == DATA_PACKET_SCO) {
SVSUTIL_ASSERT (gpHCI->transport.iScoWritePacketSize >= 0);
if (gpHCI->fScoFlow) {
int cLimit = gpHCI->sDeviceBuffer.Total_Num_SCO_Data_Packets;
if (gpHCI->transport.iScoWriteNumPackets > 0) {
cLimit = gpHCI->transport.iScoWriteNumPackets;
}
if (gpHCI->cTotalScoDataPacketsPending < cLimit) {
++pC->cScoDataPacketsPending; // per connection
++gpHCI->cTotalScoDataPacketsPending;
break;
}
} else {
if (pC->dwScoPendingPacketCount > (DWORD)gpHCI->transport.iScoWriteLowNumPackets) {
//RETAILMSG(1, (L"-low %d %d\n", pC->dwScoPendingPacketCount, pC->dwNextScoSyncTime));
// Above low threshold -- check if we are ready to send again or are out of sync, and reset accordingly
if ((int)(dwCurrTime - pC->dwNextScoSyncTime) >= (int)dwScoSyncTimeOffset) {
pC->dwScoPendingPacketCount = 0; // Off by a lot, this must be a new wave file
pC->dwNextScoSyncTime = 0;
}
else if ((int)(dwCurrTime - pC->dwNextScoSyncTime) >= 0)
pC->dwScoPendingPacketCount = gpHCI->transport.iScoWriteLowNumPackets; // Time to start sending again
}
if (pC->dwScoPendingPacketCount == gpHCI->transport.iScoWriteLowNumPackets) {
//RETAILMSG(1, (L"+low %d %d\n", pC->dwScoPendingPacketCount, pC->dwNextScoSyncTime));
// At low threshold -- set next time for syncing up
if (pC->dwNextScoSyncTime == 0)
pC->dwNextScoSyncTime = dwCurrTime;
pC->dwNextScoSyncTime += dwScoSyncTimeOffset;
}
else if (pC->dwScoPendingPacketCount == gpHCI->transport.iScoWriteNumPackets) {
//RETAILMSG(1, (L"+high %d %d\n", pC->dwScoPendingPacketCount, pC->dwNextScoSyncTime));
// At high threshold -- do not send packet
DWORD dwTimeout = (pC->dwNextScoSyncTime <= dwCurrTime) ? 0 : (pC->dwNextScoSyncTime - dwCurrTime);
if (dwTimeout < dwHciCommTimeout)
dwHciCommTimeout = dwTimeout;
pParent = pPacket;
pPacket = pPacket->pNext;
continue;
}
++pC->dwScoPendingPacketCount;
break;
}
}
}
pParent = pPacket;
pPacket = pPacket->pNext;
}
if (! pPacket) { // Can't send anything...
IFDBG(DebugOut (DEBUG_HCI_PACKETS, L"Writer : can't send anything...\n"));
gpHCI->Unlock ();
continue;
}
//
// Got packet, let's send... Reset bPacket
//
HCI_TYPE eType = pPacket->ePacketType;
bPacket.cStart = gpHCI->transport.iWriteBufferHeader;
bPacket.cEnd = bPacket.cStart + FillBuffer (pPacket, gpHCI->transport.iMaxSizeWrite, bPacket.pBuffer + bPacket.cStart);
int fCompletedPacket = FALSE;
if ((eType != DATA_PACKET_ACL) || (pPacket->uPacket.DataPacketAcl.cTotal == pPacket->uPacket.DataPacketAcl.cCompleted)) {
if (! pParent)
gpHCI->pPackets = gpHCI->pPackets->pNext;
else
pParent->pNext = pPacket->pNext;
pPacket->pNext = NULL;
if ((eType == COMMAND_PACKET) && (pPacket->uPacket.CommandPacket.eEvent == HCI_NO_EVENT))
delete pPacket;
else {
if (! gpHCI->pPacketsSent)
gpHCI->pPacketsSent = pPacket;
else {
pParent = gpHCI->pPacketsSent;
while (pParent->pNext)
pParent = pParent->pNext;
pParent->pNext = pPacket;
}
fCompletedPacket = TRUE;
}
}
gpHCI->Unlock ();
if (BufferTotal (&bPacket) <= 0)
continue;
if (! HCI_WritePacket (eType, &bPacket)) {
if (gpHCI) {
gpHCI->Lock ();
if ((gpHCI->eStage == Connected) || (gpHCI->eStage == AlmostRunning)) {
gpHCI->eStage = Error;
ShutdownTransport ();
}
gpHCI->Unlock ();
}
g_funcFree (bPacket.pBuffer, g_pvFreeData);
IFDBG(DebugOut (DEBUG_HCI_INIT, L"WT: Exiting - write failed...\n"));
return 0;
}
while ((eType != COMMAND_PACKET) && fCompletedPacket && gpHCI) {
gpHCI->Lock ();
if (gpHCI->eStage != Connected) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -