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

📄 hcibcsp.cpp

📁 Windows CE操作系统中适用的蓝牙驱动程序
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	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;
		dwSize = sizeof(dwData);
		if ((RegQueryValueEx (hk, L"Drift", NULL, &dwType, (LPBYTE)&dwData, &dwSize) == ERROR_SUCCESS) &&
			(dwType == REG_DWORD) && (dwSize == sizeof(dwData)) && dwData)
			pParms->uiDriftFactor = dwData;

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

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

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

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

		RegCloseKey (hk);
	}


#if defined (DEBUG) || defined (_DEBUG)
	pParms->iReadBufferHeader   = DEBUG_READ_BUFFER_HEADER;
	pParms->iReadBufferTrailer  = DEBUG_READ_BUFFER_TRAILER;
	pParms->iWriteBufferHeader  = DEBUG_WRITE_BUFFER_HEADER;
	pParms->iWriteBufferTrailer = DEBUG_WRITE_BUFFER_TRAILER;
#endif

	return TRUE;
}

int HCI_StartHardware (void) {
	IFDBG(DebugOut (DEBUG_HCI_INIT, L"[BCSP] HCI_StartHardware\n"));
	if (hFile != INVALID_HANDLE_VALUE) {
		IFDBG(DebugOut (DEBUG_HCI_INIT, L"[BCSP] HCI_StartHardware (already started)\n"));
		return TRUE;
	}

	if (! gCallback) {
		IFDBG(DebugOut (DEBUG_HCI_INIT, L"[BCSP] HCI_StartHardware (not registered)\n"));
		return FALSE;
	}

	return ERROR_SUCCESS == gCallback (DEVICE_UP, NULL);
}

int HCI_StopHardware (void) {
	IFDBG(DebugOut (DEBUG_HCI_INIT, L"[BCSP] HCI_StopHardware\n"));
	if (hFile == INVALID_HANDLE_VALUE) {
		IFDBG(DebugOut (DEBUG_HCI_INIT, L"[BCSP] HCI_StopHardware (already stopped)\n"));
		return TRUE;
	}

	if (! gCallback) {
		IFDBG(DebugOut (DEBUG_HCI_INIT, L"[BCSP] HCI_StopHardware (not registered)\n"));
		return FALSE;
	}

	return ERROR_SUCCESS == gCallback (DEVICE_DOWN, NULL);
}

//#error this might never be called. Init the debug somewhere else?
int HCI_SetCallback (HCI_TransportCallback pfCallback) {
	gCallback = pfCallback;

	if (gCallback)
		DebugInit();
	else
		DebugDeInit();

	return ERROR_SUCCESS;
}

int HCI_OpenConnection (void) {
	IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_OpenConnection - Started\n"));

	if (hFile != INVALID_HANDLE_VALUE) {
		IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_OpenConnection - already open, failing.\n"));
		return FALSE;
	}

	WCHAR szComPortName[_MAX_PATH];
	wcscpy (szComPortName, DEFAULT_COM_NAME);

	DWORD dwBaud = 38400;
	DWORD dwThreadPriority = DEFAULT_WORKER_THREAD_PRIORITY;
	
	HKEY hk;

	if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_BASE, L"software\\microsoft\\bluetooth\\hci", 0, KEY_READ, &hk)) {
		DWORD dwType;
		DWORD dwSize = sizeof(szComPortName);
		if ((ERROR_SUCCESS == RegQueryValueEx (hk, L"Name", NULL, &dwType, (LPBYTE)szComPortName, &dwSize)) &&
			(dwType == REG_SZ) && (dwSize > 0) && (dwSize < _MAX_PATH))
			;
		else
			wcscpy (szComPortName, DEFAULT_COM_NAME);

		dwSize = sizeof(dwBaud);
		if ((ERROR_SUCCESS == RegQueryValueEx (hk, L"baud", NULL, &dwType, (LPBYTE)&dwBaud, &dwSize)) &&
			(dwType == REG_DWORD) && (dwSize == sizeof(dwBaud)))
			;
		else
			dwBaud = 38400;

		DWORD dwData = 0;

⌨️ 快捷键说明

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