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

📄 tdi.cxx

📁 三星2440原版bsp
💻 CXX
📖 第 1 页 / 共 5 页
字号:
		pC->eStage = CLOSED;
	else
		pC->eStage = OPENED;

	PBT_CONNECT_COMPLETE		pConnectCompleteEvent    = pC->pConnectCompleteEvent;
	void						*pConnectCompleteContext = pC->pConnectCompleteContext;

	pC->pConnectCompleteContext = NULL;
	pC->pConnectCompleteEvent   = NULL;

	SVSUTIL_ASSERT (pConnectCompleteEvent);
	gpTDIR->AddRef ();
	gpTDIR->Unlock ();

	pConnectCompleteEvent (pConnectCompleteContext, iError, 0);

	gpTDIR->Lock ();
	gpTDIR->DelRef ();
}

static int SignalConnectionLoss (RFCOMM_CONNECTION_OBJECT *pC, TDI_STATUS fHow, BOOL fImmediateCleanup) {
	IFDBG(DebugOut (DEBUG_TDI_TRACE, L"SignalConnectionLoss : closing connection 0x%08x to %04x%08x 0x%02x\n", pC, GET_NAP(pC->BTAddr.btAddr), GET_SAP(pC->BTAddr.btAddr), pC->BTAddr.port));
	CONNECT_STAGE eStage = pC->eStage;

	pC->eStage = CLOSED;

	while (pC->pPacketList) {
		RFCOMM_PACKET_OBJECT	*pNext = pC->pPacketList->pNext;
		delete pC->pPacketList;
		pC->pPacketList = pNext;
	}

	int iRes = TDI_SUCCESS;

	if (pC->pConnectCompleteEvent && (! pC->fNoDisconnect)) {
		IFDBG(DebugOut (DEBUG_TDI_TRACE, L"SignalConnectionLoss : signalling connection abort to complete event\n"));
		SignalConnectionCompleteUp (pC, TDI_CONNECTION_ABORTED);
		pC = GetConnectionObject ((HANDLE)pC);
	}

	if ((! fImmediateCleanup) && (eStage == OPENED) && pC && pC->pRecvList && pC->pRecvList->pBuffer) {
		// there's still data to recv(), and we want to leave it around.
		IFDBG(DebugOut (DEBUG_TDI_TRACE, L"SignalConnectionLoss : waiting to flush the recv list...\n"));
		pC->fCloseHaveRecv = TRUE;
	} else if (pC && ((eStage == OPENED) || fImmediateCleanup || (pC->fCloseHaveRecv && (! (pC->pRecvList && pC->pRecvList->pBuffer))))) {
		pC->fCloseHaveRecv = FALSE;

		while (pC && pC->pRecvList) {
			RFCOMM_RECEIVE_OBJECT *pThis = pC->pRecvList;
			pC->pRecvList = pC->pRecvList->pNext;

			if (pThis->pBuffer && pThis->pBuffer->pFree)
				pThis->pBuffer->pFree (pThis->pBuffer);

			NDIS_BUFFER       *pNdisBuffer = pThis->pNdisBuffer;
			PBT_RECV_COMPLETE  pCallback   = pThis->pRecvEvent;
			void			  *pContext    = pThis->pRecvContext;
			int               iReceived    = pThis->iNdisUsed;

			delete pThis;

			IFDBG(DebugOut (DEBUG_TDI_TRACE, L"SignalConnectionLoss : cleaning up ndis buffer 0x%08x context 0x%08x, received %d\n", pNdisBuffer, pContext, iReceived));

			if (pNdisBuffer) {
				gpTDIR->AddRef ();
				gpTDIR->Unlock ();

				pCallback (pContext, fHow, iReceived);

				gpTDIR->Lock ();
				gpTDIR->DelRef ();
			}

			pC = GetConnectionObject ((HANDLE)pC);
		}

		while (pC && pC->pSendList) {
			RFCOMM_SEND_OBJECT *pNext = pC->pSendList->pNext;
			PBT_SEND_COMPLETE pCallback = pC->pSendList->pSendCallback;
			void *pCallbackContext = pC->pSendList->pSendContext;
			int cBytesSent = pC->pSendList->cBytesUsed;
			delete pC->pSendList;
			pC->pSendList = pNext;

			IFDBG(DebugOut (DEBUG_TDI_TRACE, L"SignalConnectionLoss : cleaning up send list context 0x%08x, sent %d\n", pCallbackContext, cBytesSent));

			gpTDIR->AddRef ();
			gpTDIR->Unlock ();

			pCallback (pCallbackContext, TDI_CONNECTION_ABORTED, cBytesSent);

			gpTDIR->Lock ();
			gpTDIR->DelRef ();

			pC = GetConnectionObject ((HANDLE)pC);
		}

		if (pC && pC->pAddr && pC->pAddr->pEventDisconnect) {
			PDisconnectEvent pEventDisconnect = pC->pAddr->pEventDisconnect;
			void *pEventContext = pC->pAddr->pEventDisconnectContext;
			void *pConnectionContext = pC->pConnectionContext;

			IFDBG(DebugOut (DEBUG_TDI_PACKETS, L"SignalConnectionLoss : forwarding up disconnection event conn 0x%08x\n", pC));

			gpTDIR->AddRef ();
			gpTDIR->Unlock ();
			iRes = pEventDisconnect (pEventContext, pConnectionContext, 0, NULL, 0, NULL,
										TDI_DISCONNECT_WAIT);
			gpTDIR->Lock ();
			gpTDIR->DelRef ();
		} else {
			IFDBG(DebugOut (DEBUG_WARN, L"[TDI] SignalConnectionLoss : nothing reported for conn 0x%08x\n", pC));
		}
	} else {
		IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] SignalConnectionLoss : already closed\n"));
		SVSUTIL_ASSERT ((! pC) || ((! pC->pSendList) && (! pC->pRecvList)));
	}

	return iRes;
}

int SendMSC (RFCOMM_CONNECTION_OBJECT *pConn, unsigned char v24out, unsigned char brout) {
	HANDLE h = gpTDIR->hRFCOMM;
	RFCOMM_MSC_In pCallback = gpTDIR->rfcomm_if.rfcomm_MSC_In;
	HANDLE hConnection = pConn->hConnect;

	unsigned char v24 = TDIR_V24_CONST | (pConn->fc_local ? TDIR_V24_FC : 0) | v24out;

	gpTDIR->AddRef ();
	gpTDIR->Unlock ();

	int iRes = ERROR_INTERNAL_ERROR;
	__try {
		iRes = pCallback (h, NULL, hConnection, v24, brout);
	} __except (1) {
		IFDBG(DebugOut (DEBUG_ERROR, L"[TDIR] SendMSC Exception in rfcomm_MSC_In\n"));
	}

	gpTDIR->Lock ();
	gpTDIR->DelRef ();

	return iRes;
}

int SendRLS (RFCOMM_CONNECTION_OBJECT *pConn, unsigned char rls) {
	HANDLE h = gpTDIR->hRFCOMM;
	RFCOMM_RLS_In pCallback = gpTDIR->rfcomm_if.rfcomm_RLS_In;
	HANDLE hConnection = pConn->hConnect;

	gpTDIR->AddRef ();
	gpTDIR->Unlock ();

	int iRes = ERROR_INTERNAL_ERROR;
	__try {
		iRes = pCallback (h, NULL, hConnection, rls);
	} __except (1) {
		IFDBG(DebugOut (DEBUG_ERROR, L"[TDIR] SendMSC Exception in rfcomm_MSC_In\n"));
	}

	gpTDIR->Lock ();
	gpTDIR->DelRef ();

	return iRes;
}

static DWORD WINAPI StackDisconnect (LPVOID lpUnused) {
	tdiR_CloseDriverInstance ();
	return 0;
}

static DWORD WINAPI StackXXX (LPVOID lpWhat) {
	IFDBG(DebugOut (DEBUG_TDI_TRACE, L"+StackXXX\n"));
	if (! gpTDIR) {
		IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] StackXXX : ERROR_SERVICE_NOT_ACTIVE\n"));
		return ERROR_SERVICE_NOT_ACTIVE;
	}

	for ( ; ; ) {
		gpTDIR->Lock ();

		if (! gpTDIR->fIsInitialized) {
			IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] StackXXX : ERROR_SERVICE_NOT_ACTIVE\n"));
			gpTDIR->Unlock ();
			return ERROR_SERVICE_NOT_ACTIVE;
		}

		if (gpTDIR->GetRefCount() == 1)
			break;

		IFDBG(DebugOut (DEBUG_TDI_TRACE, L"Waiting for ref count in StackXXX\n"));
		gpTDIR->Unlock ();
		Sleep (100);
	}

	if ((int)lpWhat == 1) {
		gpTDIR->fIsConnected = TRUE;
	} else if (((int)lpWhat == 2) || ((int)lpWhat == 3)) {

		while (gpTDIR->pnlist) {
			RFCOMM_PN_OBJECT *pNext = gpTDIR->pnlist->pNext;
			delete gpTDIR->pnlist;
			gpTDIR->pnlist = pNext;
		}

		gpTDIR->fIsConnected = FALSE;
		gpTDIR->AddRef ();

		for ( ; ; ) {
			RFCOMM_CONNECTION_OBJECT *pC = gpTDIR->pcolist;
			while (pC && (pC->eStage != OPENED) && (pC->eStage != OPENING))
				pC = pC->pNext;

			if (! pC)
				break;

			SignalConnectionLoss (pC, TDI_CONNECTION_ABORTED, TRUE);
		}

		gpTDIR->DelRef ();
		if ((int)lpWhat == 3)
			gpTDIR->fIsConnected = TRUE;
	}

	int iErr = ERROR_SUCCESS;
	if (gpTDIR->fIsConnected) {
		HANDLE h = gpTDIR->hHCI;
		HCI_ReadBDADDR_In pCallback = gpTDIR->hci_if.hci_ReadBDADDR_In;
		gpTDIR->AddRef ();
		gpTDIR->Unlock ();

		__try {
			iErr = pCallback (h, NULL);
		} __except (1) {
			iErr = ERROR_INTERNAL_ERROR;
			IFDBG(DebugOut (DEBUG_ERROR, L"[TDIR] : exception in StackXXX!\n"));
		}

		gpTDIR->Lock ();
		gpTDIR->DelRef ();
	}
	else
		gpTDIR->btAddr = SET_NAP_SAP(0, 0);

	IFDBG(DebugOut (DEBUG_TDI_TRACE, L"-StackXXX ERROR_SUCCESS\n"));
	gpTDIR->Unlock ();

	return iErr;
}

static int QueryNdisSize (NDIS_BUFFER *pNdisB) {
	int cSize = 0;
	while (pNdisB) {
		PVOID pVA = NULL;
		unsigned int uiLength = 0;

		NdisQueryBuffer (pNdisB, &pVA, &uiLength);

		if (! pVA)
			break;

		cSize += uiLength;
		NdisGetNextBuffer(pNdisB, &pNdisB);
	}

	return cSize;
}

static int CopyNdisToFlat
(
NDIS_BUFFER		*pNdisB,
unsigned char	*pFlatBuf,
int				cCount,
int				cStartOffset
) {
	int cOffset = 0;
	int cCopied = 0;
	while (pNdisB) {
		unsigned char *pVA = NULL;
		unsigned int uiLength = 0;

		NdisQueryBuffer (pNdisB, (PVOID *)&pVA, &uiLength);

		if (! pVA)
			break;

		if (cOffset + (int)uiLength > cStartOffset) {
			SVSUTIL_ASSERT (cOffset <= cStartOffset);
			int cBytesAvailable = cOffset + uiLength - cStartOffset;
			int cOffsetInBuffer = cStartOffset - cOffset;
			int cBytesToCopy = cBytesAvailable > cCount ? cCount : cBytesAvailable;
			memcpy (pFlatBuf, pVA + cOffsetInBuffer, cBytesToCopy);

			cCount -= cBytesToCopy;
			cStartOffset += cBytesToCopy;
			cCopied += cBytesToCopy;
			pFlatBuf += cBytesToCopy;

			SVSUTIL_ASSERT (cCount >= 0);

			if (cCount == 0)
				break;
		}

		cOffset += uiLength;
		NdisGetNextBuffer(pNdisB, &pNdisB);
	}

	return cCopied;
}

static int CountPendingSends (RFCOMM_CONNECTION_OBJECT *pConn) {
	RFCOMM_SEND_OBJECT *pSendList = pConn->pSendList;
	int cTotalSize = 0;

	while (pSendList) {
		int cBytes = QueryNdisSize (pSendList->pNdisBuffer) - pSendList->cBytesUsed;
		SVSUTIL_ASSERT (cBytes >= 0);
		cTotalSize += cBytes;
		pSendList = pSendList->pNext;
	}

	return cTotalSize;
}

static int TransferPendingSends (RFCOMM_CONNECTION_OBJECT *pConn, unsigned char *pBuff, int cBuff) {
	RFCOMM_SEND_OBJECT *pSendList = pConn->pSendList;
	int cTotalSent = 0;

	while (pSendList && (cBuff > 0)) {
		int cBytes = QueryNdisSize (pSendList->pNdisBuffer) - pSendList->cBytesUsed;
		SVSUTIL_ASSERT (cBytes >= 0);
		if (cBytes > cBuff)
			cBytes = cBuff;

		if (cBytes > 0) {
			int cTransf = CopyNdisToFlat (pSendList->pNdisBuffer, pBuff, cBytes, pSendList->cBytesUsed);
			SVSUTIL_ASSERT (cTransf == cBytes);

			cBuff -= cBytes;
			pBuff += cBytes;
			pSendList->cBytesUsed += cBytes;
		}

		cTotalSent += cBytes;
		pSendList = pSendList->pNext;
	}

	SVSUTIL_ASSERT (cBuff == 0);
	return cTotalSent;
}

static int GetQuota (RFCOMM_CONNECTION_OBJECT *pC) {
	if (pC->fc_credit && (pC->imax_recv < (pC->mtu * 2 * PORTEMU_CREDITS_LOWEST)))
		return pC->mtu * 2 * PORTEMU_CREDITS_LOWEST;

	return pC->imax_recv;
}

static int GiveCredits (RFCOMM_CONNECTION_OBJECT *pC) {
	if ((! pC->fc_credit) || (pC->iGaveCredits > PORTEMU_CREDITS_LOW))
		return 0;

	int nCredits = (GetQuota (pC) - pC->irecvd) / pC->mtu - pC->iGaveCredits;

	return nCredits > 0 ? nCredits : 0;
}

static void SendCredits (RFCOMM_CONNECTION_OBJECT *pC) {
	SVSUTIL_ASSERT (pC->fc_credit);

	if (pC->iGaveCredits > PORTEMU_CREDITS_LOWEST)
		return;

	int nCredits = (GetQuota (pC) - pC->irecvd) / pC->mtu - pC->iGaveCredits;

	if (nCredits <= 0)
		return;

	IFDBG(DebugOut (DEBUG_TDI_PACKETS, L"[TDIR] SendCredits 0x%08x : sending %d credits\n", pC, nCredits));

	BD_BUFFER *pBuffer = BufferAlloc (gpTDIR->cDeviceHeader + gpTDIR->cDeviceTrailer + DEBUG_OVERHEAD);

	if (! pBuffer) {
		IFDBG(DebugOut (DEBUG_ERROR, L"[TDIR] SendCredits 0x%08x :  <out of memory>\n", pC));
		return;
	}

	pBuffer->cStart = gpTDIR->cDeviceHeader;
	pBuffer->cEnd   = pBuffer->cSize - gpTDIR->cDeviceTrailer;

	SVSUTIL_ASSERT (BufferTotal (pBuffer) == DEBUG_OVERHEAD);

	pC->iGaveCredits += nCredits;

#if defined (DEBUG_CREDIT_FLOW)
	pC->iCreditsSent += nCredits;
#endif

#if defined (DEBUG_PEER_SYNCHRONIZATION)
	PeerDebugData pd;

#if defined (DEBUG_CREDIT_FLOW)
	pd.iGaveCredits = pC->iGaveCredits;
	pd.iHaveCredits = pC->iHaveCredits;
	pd.iPacketsRecv = pC->iPacketsRecv;
	pd.iPacketsSent = pC->iPacketsSent;
	pd.iCreditsRecv = pC->iCreditsRecv;
	pd.iCreditsSent = pC->iCreditsSent;
#endif

	SVSUTIL_ASSERT (sizeof(pd) == DEBUG_OVERHEAD);
	memcpy (pBuffer->pBuffer + pBuffer->cEnd - sizeof(pd), &pd, sizeof(pd));
#endif

	HANDLE h = gpTDIR->hRFCOMM;
	HANDLE hConn = pC->hConnect;
	RFCOMM_DataDown_In pCallback = gpTDIR->rfcomm_if.rfcomm_DataDown_In;

	gpTDIR->Unlock ();
	__try {
		pCallback (h, NULL, hConn, pBuffer, nCredits);
	} __except (1) {
		IFDBG(DebugOut (DEBUG_ERROR, L"[TDIR] SendCredits : exception in rfcomm_DataDown_In\n"));
	}

	gpTDIR->Lock ();
}

static TDI_STATUS SendData (RFCOMM_CONNECTION_OBJECT *pConn) {
	if (pConn != GetConnectionObject ((HANDLE)pConn)) {
		IFDBG(DebugOut (DEBUG_WARN, L"[TDIR] SendData : Connection 0x%08x not found\n", pConn));
		return TDI_INVALID_CONNECTION;
	}

	if (pConn->fSending)		// Guard against packets coming out of order
		return TDI_PENDING;

	for ( ; ; ) {
		if (! gpTDIR->fIsConnected) {
			IFDBG(DebugOut (DEBUG_WARN, L"[TDIR] SendData : disconnected\n"));
			return TDI_INVALID_STATE;
		}

		if (pConn->eStage != OPENED) {
			IFDBG(DebugOut (DEBUG_WARN, L"[TDIR] SendData : Connection 0x%08x not OPEN\n", pConn));
			return TDI_CONNECTION_RESET;
		}

		if ((pConn->isent >= pConn->imax_send) ||
			(pConn->fc_credit && (pConn->iHaveCredits <= 0)) ||
			((! pConn->fc_credit) && (pConn->fc_remote || pConn->fc_aggregate)))
			break;

		int cSend = CountPendingSends (pConn);
		SVSUTIL_ASSERT (cSend >= 0);

		if (cSend == 0) {
			if (pConn->fCloseHaveSend) {
				SignalConnectionLoss (pConn, TDI_GRACEFUL_DISC, TRUE);
				if (gpTDIR->fIsInitialized && (pConn == GetConnectionObject ((HANDLE)pConn)))
					DisconnectConnection (pConn, NULL, NULL);

⌨️ 快捷键说明

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