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

📄 hci.cxx

📁 三星2440原版bsp
💻 CXX
📖 第 1 页 / 共 5 页
字号:
		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 + -