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

📄 hcibcsp.cpp

📁 三星2440原版bsp
💻 CPP
📖 第 1 页 / 共 5 页
字号:

	BCSPPacket syncRespPacket;
	syncRespPacket.SetData(syncRespPayload, 4);
	syncRespPacket.header.ack = 0;
	syncRespPacket.header.seq = 0;
	syncRespPacket.header.crcPresent = 0;
	syncRespPacket.header.payloadLength = 4;
	syncRespPacket.header.protocolID = 1;
	syncRespPacket.header.protocolType = 0;

	const unsigned char confPayload[] = { 0xAD, 0xEF, 0xAC, 0xED };

	BCSPPacket confPacket;
	confPacket.SetData(confPayload, 4);
	confPacket.header.ack = 0;
	confPacket.header.seq = 0;
	confPacket.header.crcPresent = 0;
	confPacket.header.payloadLength = 4;
	confPacket.header.protocolID = 1;
	confPacket.header.protocolType = 0;

	IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[BCSP] BCSPLinkEstablishmentThread : SYNC\n"));

	if (syncPacket.WriteToCOMPort (FALSE)) {
		int iCount = 0;

		while (iCount < BCSP_RETRY_LIMIT) {
			DWORD ret = WaitForMultipleObjects (2, (HANDLE *)phandles, FALSE, BCSP_PASSIVE_TIMEOUT);

			if(WAIT_OBJECT_0 == ret) {
				IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[BCSP] BCSPLinkEstablishmentThread : got SYNC-RESP, sending CONF and returning\n"));
				return confPacket.WriteToCOMPort (FALSE);
			} else if (WAIT_OBJECT_0 + 1 == ret) {
				IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[BCSP] BCSPLinkEstablishmentThread : got SYNC, send SYNC-RESP\n"));

				if (! syncRespPacket.WriteToCOMPort (FALSE))
					break;
			} else {
				ASSERT (ret == WAIT_TIMEOUT);
				IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[BCSP] BCSPLinkEstablishmentThread : timeout, resending SYNC\n"));

				if (! syncPacket.WriteToCOMPort (FALSE))
					break;

				++iCount;
			}
		}
	}

	IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] BCSPLinkEstablishmentThread : closing port and dying\n"));
	CloseCommPort ();

	return FALSE;
}

static int BCSPLinkEstablishment (void) {
#ifndef BCSP_NO_LINK_ESTABLISHMENT
	unsigned char payload[PACKET_SIZE_R];
	BCSPHeader syncHeader;

	const unsigned char syncPayload[] = { 0xDA, 0xDC, 0xED, 0xED };
	const unsigned char syncRespPayload[] = { 0xAC, 0xAF, 0xEF, 0xEE };

	payload[0] = 0;

	HANDLE hLinkEstablishmentThreadDie    = CreateEvent (NULL, TRUE, FALSE, NULL);
	HANDLE hLinkEstablishmentSyncReceived = CreateEvent (NULL, FALSE, FALSE, NULL);

	HANDLE handles[2] = { hLinkEstablishmentThreadDie, hLinkEstablishmentSyncReceived };

	HANDLE hThread = CreateThread(NULL, 0, BCSPLinkEstablishmentThread, handles, 0, NULL);

	int iRes = FALSE;

	while (TRUE) {
		if (! ReadFromCOMPort(&syncHeader, payload))
			break;

		if (syncHeader.payloadLength != 4)
			continue;

		if (0 == memcmp(syncPayload, payload, 4))
			SetEvent(hLinkEstablishmentSyncReceived);
		else if (0 == memcmp(syncRespPayload, payload, 4)) {
			iRes = TRUE;
			break;
		}
	}

	SetEvent(hLinkEstablishmentThreadDie);

	WaitForSingleObject (hThread, INFINITE);

	CloseHandle (hThread);
	CloseHandle(hLinkEstablishmentThreadDie);
	CloseHandle(hLinkEstablishmentSyncReceived);

	hLinkEstablishmentSyncReceived = NULL;

	return iRes;
#else
	return TRUE;
#endif
}

//
//	Protocol procedures : transmission thread
//
static int SYNCSendPureAck (DWORD ack) {
	IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[BCSP] SendPureAck (%d)\n", ack));

	BCSPPacket packet;
	packet.header.ack = ack;
	packet.header.seq = 0;
	packet.header.crcPresent = 0;
	packet.header.payloadLength = 0;
	packet.header.protocolID = 0;
	packet.header.protocolType = 0;
	packet.header.SetChecksum();

	packet.SetData(0, 0);

	return packet.WriteToCOMPort(TRUE);
}

static int BCSPProcessAcks (void) {
	if (g_iRxAckLast != g_iRxAck) {
		IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] BCSPProcessAcks: got an ack for seq %d\n", g_iRxAckLast));
		// find the non-new packet that corresponds to this ack

		BCSPPacketListNode *pPacketListNode = g_pTransmitPackets;
		while(pPacketListNode && (! pPacketListNode->packet.fNewPacket) && 
			((pPacketListNode->packet.header.seq + 1) & BCSP_SEQ_MASK) != g_iRxAckLast)
			pPacketListNode = pPacketListNode->next;
		
		// if the pointer is non-zero and we have an old packet we must have the packet that
		//  has been acked
		if(pPacketListNode && (! pPacketListNode->packet.fNewPacket)) {
			// free all old packets in the transmit queue up to and including the acked packet
			BCSPPacketListNode *pCurrent = g_pTransmitPackets;

			g_pTransmitPackets = pPacketListNode->next;

			while(pCurrent && (pCurrent != g_pTransmitPackets)) {
				IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] BCSPProcessAcks: retiring packet %d\n", pCurrent->packet.header.seq));
				BCSPPacketListNode* pNext = pCurrent->next;
				delete pCurrent;
				pCurrent = pNext;
			}

			SetEvent(g_hCanTransmitPacket);
			g_iRxAck = g_iRxAckLast;

			return TRUE;
		}
	} else
		IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] BCSPProcessAcks: already processed for seq %d\n", g_iRxAckLast));

	return FALSE;			// no packet was removed
}

static DWORD WINAPI BCSPWriteThread (LPVOID) {
	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] BCSPWriteThread: spinning up...\n"));

	DWORD activeTimeout = INFINITE;
	int retries = BCSP_RETRY_LIMIT;			// retries left to oldest packet
	int fWriteError = FALSE;

	while ((! g_fShutDown) && (! fWriteError)) {
		DWORD ret = WaitForSingleObject (g_hWriteThreadEvent, activeTimeout);

		IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] BCSPWriteThread : woke up @ tick %d, timeout was %d ms.\n", GetTickCount (), activeTimeout));

		if (g_fShutDown) {
			IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] BCSPWriteThread : shutdown detected\n"));
			break;
		}

		InterlockedIncrement ((LONG *)&g_iRxSyncs);
		while ((! g_fShutDown) && (InterlockedDecrement ((LONG *)&g_iRxSyncs) > 0)) {
			IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] BCSPWriteThread : sending SYNC-RESP.\n"));
	
			const unsigned char syncRespPayload[] = { 0xAC, 0xAF, 0xEF, 0xEE };
			BCSPPacket syncRespPacket;

			syncRespPacket.SetData(syncRespPayload, 4);
			syncRespPacket.header.ack = 0;
			syncRespPacket.header.seq = 0;
			syncRespPacket.header.crcPresent = 0;
			syncRespPacket.header.payloadLength = 4;
			syncRespPacket.header.protocolID = 1;
			syncRespPacket.header.protocolType = 0;

			if (! syncRespPacket.WriteToCOMPort (FALSE)) {
				IFDBG(DebugOut(DEBUG_ERROR, L"[BCSP] BCSPWriteThread : WriteToCOMPort failed, ERROR\n"));
				fWriteError = TRUE;
				break;
			}
		}

		InterlockedIncrement ((LONG *)&g_iRxConfs);
		while ((! g_fShutDown) && (InterlockedDecrement ((LONG *)&g_iRxConfs) > 0)) {
			IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] BCSPWriteThread : sending CONF-RESP.\n"));
	
			const unsigned char confRespPayload[] = { 0xde, 0xad, 0xd0, 0xd0 };
			BCSPPacket confRespPacket;

			confRespPacket.SetData(confRespPayload, 4);
			confRespPacket.header.ack = 0;
			confRespPacket.header.seq = 0;
			confRespPacket.header.crcPresent = 0;
			confRespPacket.header.payloadLength = 4;
			confRespPacket.header.protocolID = 1;
			confRespPacket.header.protocolType = 0;

			if (! confRespPacket.WriteToCOMPort (FALSE)) {
				IFDBG(DebugOut(DEBUG_ERROR, L"[BCSP] BCSPWriteThread : WriteToCOMPort failed, ERROR\n"));
				fWriteError = TRUE;
				break;
			}
		}

		SVSLocalCriticalSection cs (&g_csBCSP);

		if (g_fShutDown || fWriteError) {
			IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] BCSPWriteThread : shutdown or write error detected\n"));
			break;
		}

		ASSERT (GetListSize () <= BCSP_WIN_SIZE);

		// Handle SCO packets first
		while (1) {
			BCSPPacketListNode *pSCOPacket = GetNextSCOPacket();
			if (pSCOPacket) {
				IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] BCSPWriteThread : Sending SCO packet\n"));
				fWriteError = ! pSCOPacket->packet.WriteToCOMPort (FALSE); // This unlocks
				if (fWriteError) {
					IFDBG(DebugOut(DEBUG_ERROR, L"[BCSP] BCSPWriteThread failed on send SCO packet.\n"));
				}
				delete pSCOPacket; // Delete SCO packet once sent
				SetEvent(g_hCanTransmitPacket);
			}
			else {
				break;
			}
		}

		if (BCSPProcessAcks ()) {
			ret = WAIT_OBJECT_0;			// the timeout doesn't matter since the oldest
											//  packet was acked and removed from the queue
			retries = BCSP_RETRY_LIMIT;
		}

		// If the oldest packet timed out, resend it and all other non-new packets.
		if (ret == WAIT_TIMEOUT) { 
			if (retries-- <= 0) {
				IFDBG(DebugOut(DEBUG_ERROR, L"[BCSP] BCSPWriteThread: retry limit reached.\n"));
				break;
			}

			BCSPPacketListNode *pPacketListNode = g_pTransmitPackets;

			int cNumRetrans = 0;

			while (pPacketListNode) {
				if (pPacketListNode->packet.header.protocolType) {
					IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] BCSPWriteThread: marking seq %d for resend.\n", pPacketListNode->packet.header.seq));
					pPacketListNode->packet.fResendPacket = TRUE;

					if (! pPacketListNode->packet.fNewPacket)
						++cNumRetrans;
				}
				pPacketListNode = pPacketListNode->next;
			}

			if (cNumRetrans == 0)			// Nothing to retransmit, reset the counter
				retries = BCSP_RETRY_LIMIT;
			else {
				IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] BCSPWriteThread: retry %d (%d packets).\n", retries, cNumRetrans));
			}
		}

		// if new packets are in the transmit queue then send them off
		BCSPPacketListNode *pNewPacket = NULL;

		while ((! g_fShutDown) && (! fWriteError) && (pNewPacket = GetFirstPacketForSend())) {
			if (pNewPacket->packet.header.protocolType) { // If reliable packet type
				if (pNewPacket->packet.fNewPacket) {
					pNewPacket->packet.header.seq = g_iTxSeq;
					g_iTxSeq = (g_iTxSeq + 1) & BCSP_SEQ_MASK;

					pNewPacket->packet.fNewPacket = FALSE;
				}

				pNewPacket->packet.fResendPacket = FALSE;
				pNewPacket->packet.header.ack = g_iTxAck;

				IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] BCSPWriteThread: sending seq %d.\n", pNewPacket->packet.header.seq));

				g_iTxUnack = 0;
				g_dwTxAckDue = 0;
			}
			
			fWriteError = ! pNewPacket->packet.WriteToCOMPort (TRUE); // This unlocks

			if (fWriteError) {
				IFDBG(DebugOut(DEBUG_ERROR, L"[BCSP] BCSPWriteThread failed on send.\n"));
			}	
		}

		if ((! g_fShutDown) && (! fWriteError)) {
			if ((!pNewPacket) || (pNewPacket->packet.header.protocolType)) {
				if ((g_iTxUnack >= (BCSP_WIN_SIZE-1)) || ((g_iTxUnack > 0) && (((int)GetTickCount () - (int)g_dwTxAckDue) >= 0))) {
					g_iTxUnack = 0;
					g_dwTxAckDue = 0;

					fWriteError = ! SYNCSendPureAck(g_iTxAck);	// This unlocks

					if (fWriteError) {
						IFDBG(DebugOut(DEBUG_ERROR, L"[BCSP] BCSPWriteThread failed on ack send.\n"));
					}	
				}
			}
		}

		if ((! g_fShutDown) && (! fWriteError)) {
			if ((!pNewPacket) || (pNewPacket->packet.header.protocolType)) {
				if (g_iTxUnack) {
					activeTimeout = (DWORD)((int)g_dwTxAckDue - (int)GetTickCount ());
					if (activeTimeout > BCSP_ACTIVE_TIMEOUT) {
						activeTimeout = 0;
						IFDBG(DebugOut(DEBUG_WARN, L"[BCSP] BCSPWriteThread : active timeout reset to 0\n"));
					}
				} 
				else if (g_pTransmitPackets) {
					activeTimeout = BCSP_ACTIVE_TIMEOUT;
				}
				else {
					activeTimeout = INFINITE;
				}
			}
		}
	}

	IFDBG(DebugOut(DEBUG_ERROR, L"[BCSP] BCSPWriteThread :: closing COM port and dying.\n"));
	CloseCommPort ();	// unblock the read...

	return 0;
}

//
//	Stack management functions
//
int HCI_ReadHciParameters (HCI_PARAMETERS *pParms) {
	if (pParms->uiSize < sizeof (*pParms))
		return FALSE;

	memset (pParms, 0, sizeof(*pParms));

	pParms->uiSize             = sizeof(*pParms);
	pParms->fInterfaceVersion  = HCI_INTERFACE_VERSION_1_1;
	pParms->iMaxSizeRead       = PACKET_SIZE_R;
	pParms->iMaxSizeWrite      = PACKET_SIZE_W;
	pParms->iWriteBufferHeader = 4;
	pParms->iReadBufferHeader  = 4;
	pParms->fHardwareVersion   = HCI_HARDWARE_VERSION_V_1_0_B;
	pParms->uiWriteTimeout     = HCI_DEFAULT_WRITE_TIMEOUT;
	pParms->uiDriftFactor      = HCI_DEFAULT_DRIFT;
	pParms->uiFlags            = 0;

	pParms->iScoWriteLowNumPackets	= SCO_DEFAULT_WRITE_LOW_NUM_PACKETS;
	pParms->iScoWriteNumPackets 		= SCO_DEFAULT_WRITE_HIGH_NUM_PACKETS;
	pParms->iScoWritePacketSize		= SCO_DEFAULT_PACKET_SIZE;
	pParms->iScoSampleSize			= SCO_DEFAULT_SAMPLE_SIZE;

	HKEY hk;

	if (RegOpenKeyEx (HKEY_BASE, L"Software\\Microsoft\\Bluetooth\\hci", 0, KEY_READ, &hk) == ERROR_SUCCESS) { 
		DWORD dwType = 0;
		DWORD dwData = 0;
		DWORD dwSize = sizeof(dwData);
		if ((RegQueryValueEx (hk, L"ResetDelay", NULL, &dwType, (LPBYTE)&dwData, &dwSize) == ERROR_SUCCESS) &&
			(dwType == REG_DWORD) && (dwSize == sizeof(dwData)) && dwData)
			pParms->uiResetDelay = dwData;

		dwData = 0;
		dwSize = sizeof(dwData);
		if ((RegQueryValueEx (hk, L"SpecV10a", NULL, &dwType, (LPBYTE)&dwData, &dwSize) == ERROR_SUCCESS) &&
			(dwType == REG_DWORD) && (dwSize == sizeof(dwData)) && dwData)
			pParms->fHardwareVersion = HCI_HARDWARE_VERSION_V_1_0_A;

		dwData = 0;
		dwSize = sizeof(dwData);
		if ((RegQueryValueEx (hk, L"SpecV11", NULL, &dwType, (LPBYTE)&dwData, &dwSize) == ERROR_SUCCESS) &&
			(dwType == REG_DWORD) && (dwSize == sizeof(dwData)) && dwData)
			pParms->fHardwareVersion = HCI_HARDWARE_VERSION_V_1_1;

		dwData = 0;
		dwSize = sizeof(dwData);
		if ((RegQueryValueEx (hk, L"WriteTimeout", NULL, &dwType, (LPBYTE)&dwData, &dwSize) == ERROR_SUCCESS) &&
			(dwType == REG_DWORD) && (dwSize == sizeof(dwData)) && dwData)
			pParms->uiWriteTimeout = dwData;

		dwData = 0;
		dwSize = sizeof(dwData);
		if ((RegQueryValueEx (hk, L"Flags", NULL, &dwType, (LPBYTE)&dwData, &dwSize) == ERROR_SUCCESS) &&
			(dwType == REG_DWORD) && (dwSize == sizeof(dwData)) && dwData)
			pParms->uiFlags = dwData;

		dwData = 0;

⌨️ 快捷键说明

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