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

📄 hcibcsp.cpp

📁 Windows CE操作系统中适用的蓝牙驱动程序
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		dwSize = sizeof(dwData);

		if ((ERROR_SUCCESS == RegQueryValueEx (hk, L"Priority256", NULL, &dwType, (LPBYTE)&dwData, &dwSize)) &&
			(dwType == REG_DWORD) && (dwSize == sizeof(dwData)))
			dwThreadPriority = dwData;

		RegCloseKey (hk);
	}

	IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[BCSP] Opening port %s (rate %d) for I/O with unit\n", szComPortName, dwBaud));

    hFile = CreateFile(szComPortName,
                GENERIC_READ | GENERIC_WRITE,
                0,    // comm devices must be opened w/exclusive-access
                NULL, // no security attrs
                OPEN_EXISTING, // comm devices must use OPEN_EXISTING
                FILE_ATTRIBUTE_NORMAL,    // overlapped I/O 
                NULL  // hTemplate must be NULL for comm devices  
				);

    if (hFile == INVALID_HANDLE_VALUE) {
		IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] Failed CreateFile in BCSP HCI Interface. GetLastError = 0x%08x\n", GetLastError ()));
		return FALSE;

    }

    if (! SetupComm (hFile, 4096, 4096)) {
		CloseCommPort ();

		IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] Failed SetupComm in BCSP HCI Interface. GetLastError = 0x%08x\n", GetLastError ()));
		return FALSE;
    } 

    // purge any information in the buffer

//    if ( ! PurgeComm (hFile, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR )) {
//		CloseCommPort ();
//
//		IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] Failed PurgeComm in BCSP HCI Interface. GetLastError = 0x%08x\n", GetLastError ()));
//		return FALSE;
//    }

	DCB dcb;

    if (! GetCommState(hFile, &dcb)) {
		CloseCommPort ();

		IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] Failed GetCommState in BCSP HCI Interface. GetLastError = 0x%08x\n", GetLastError ()));
		return FALSE;
    }

    dcb.BaudRate = dwBaud;
    dcb.fDtrControl = DTR_CONTROL_ENABLE;
    dcb.fRtsControl = RTS_CONTROL_ENABLE;

    dcb.fAbortOnError = FALSE;

    dcb.ByteSize =8;
    dcb.fParity = TRUE;
    dcb.Parity = EVENPARITY;
    dcb.StopBits = ONESTOPBIT;
    dcb.ErrorChar = -64;

    if (! SetCommState(hFile, &dcb)) {
		CloseCommPort ();

		IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] Failed SetCommState in BCSP HCI Interface. GetLastError = 0x%08x\n", GetLastError ()));
		return FALSE;
    }

    COMMTIMEOUTS CommTimeOuts;
    CommTimeOuts.ReadIntervalTimeout = 1 ;
    CommTimeOuts.ReadTotalTimeoutMultiplier = 0 ;
    CommTimeOuts.ReadTotalTimeoutConstant = 1000 ;
    CommTimeOuts.WriteTotalTimeoutMultiplier = 0 ;
    CommTimeOuts.WriteTotalTimeoutConstant = 1000 ;

    if (! SetCommTimeouts (hFile, &CommTimeOuts)) {
		CloseCommPort ();

		IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] Failed SetCommTimeouts in BCSP HCI Interface. GetLastError = 0x%08x\n", GetLastError ()));
		return FALSE;
    }

#if defined (BT_USE_CELOG)
	if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_BASE, L"software\\microsoft\\bluetooth\\debug", 0, KEY_READ, &hk)) {
		DWORD dwType;
		DWORD dw;
		DWORD dwSize = sizeof(dw);

		if ((ERROR_SUCCESS == RegQueryValueEx (hk, L"celog", NULL, &dwType, (LPBYTE)&dw, &dwSize)) &&
			(dwType == REG_DWORD) && (dwSize == sizeof(dw)) && dw)
			g_fCeLog = IsCeLogStatus (CELOGSTATUS_ENABLED_GENERAL);

		RegCloseKey (hk);
	}

	if (g_fCeLog) {
#if defined (SDK_BUILD)
		CELOGSDK_START ();
#endif

		BTH_CELOG_START_DATA sd;

		sd.eTransport = BCSP;
		GetLocalTime (&sd.st);
		wsprintf (sd.szDriverString, L"BCSP Driver v. 0x%08x on %s", HCI_INTERFACE_VERSION_1_1, szComPortName);

		CELOGDATAFLAGGED(TRUE, CELID_RAW_UCHAR, &sd, sizeof(sd), 0, CELZONE_ALWAYSON, CELOG_FLAG_START);
	}
#endif

	g_fShutDown = FALSE;

	ReinitGlobals ();

	g_pWriteBuff = (unsigned char*) malloc (MAX_BUFFER_SIZE);
	if (! g_pWriteBuff) {
		CloseCommPort ();

		IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_OpenConnection failed: Error allocating write buffer.\n"));
		return FALSE;
	}

	g_hCanTransmitPacket = CreateEvent (NULL, FALSE, FALSE, NULL);
	g_hWriteThreadEvent  = CreateEvent (NULL, FALSE, FALSE, NULL);
	g_hPacketReady       = CreateEvent (NULL, FALSE, FALSE, NULL);

	g_pfmdPacketDescr = svsutil_AllocFixedMemDescr (sizeof(SerialPacket), 10);

	InitializeCriticalSection (&g_csBCSP);
	InitializeCriticalSection (&g_csPackets);

	g_hReadThread  = CreateThread (NULL, 0, COMReadThread, NULL, 0, NULL);
	g_hWriteThread = CreateThread (NULL, 0, BCSPWriteThread, NULL, 0, NULL);

	CeSetThreadPriority(g_hReadThread, dwThreadPriority);
	CeSetThreadPriority(g_hWriteThread, dwThreadPriority);

	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_OpenConnection: Attempting BCSP link establishment.\n"));
	
	if (! BCSPLinkEstablishment()) {
		HCI_CloseConnection ();

		IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_OpenConnection failed: Could not complete BCSP link establishment.\n"));
		return FALSE;
	}

	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_OpenConnection: BCSP link establishment complete.\n"));
	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_OpenConnection: Successful.\n"));

	return TRUE;
}

void HCI_CloseConnection (void) {
	if (g_fShutDown) {
		IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_CloseConnection: already in shutdown.\n"));
		return;
	}

	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_CloseConnection: entered.\n"));

	CloseCommPort ();

	EnterCriticalSection (&g_csBCSP);
	g_fShutDown = TRUE;

	SetEvent (g_hCanTransmitPacket);
	CloseHandle(g_hCanTransmitPacket);

	SetEvent (g_hWriteThreadEvent);
	CloseHandle(g_hWriteThreadEvent);

	SetEvent (g_hPacketReady);
	CloseHandle (g_hPacketReady);

	if (g_pWriteBuff) {
		free (g_pWriteBuff);
		g_pWriteBuff = NULL;
	}

	while (g_pTransmitPackets) {
		BCSPPacketListNode *pNext = g_pTransmitPackets->next;
		delete g_pTransmitPackets;
		g_pTransmitPackets = pNext;
	}

	while (g_pSCOTransmitPackets) {
		BCSPPacketListNode *pNext = g_pSCOTransmitPackets->next;
		delete g_pSCOTransmitPackets;
		g_pSCOTransmitPackets = pNext;
	}

	LeaveCriticalSection (&g_csBCSP);
	DeleteCriticalSection(&g_csBCSP);

	if (g_hWriteThread) {
		WaitForSingleObject (g_hWriteThread, INFINITE);
		CloseHandle (g_hWriteThread);
	}

	if (g_hReadThread) {
		WaitForSingleObject (g_hReadThread, INFINITE);
		CloseHandle (g_hReadThread);
	}

	EnterCriticalSection (&g_csPackets);
	svsutil_ReleaseFixedNonEmpty (g_pfmdPacketDescr);
	g_pfmdPacketDescr = NULL;
	g_pPackets = NULL;
	LeaveCriticalSection (&g_csPackets);
	DeleteCriticalSection(&g_csPackets);

	ReinitGlobals ();

	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_CloseConnection: success\n"));
}

int HCI_ReadPacket (HCI_TYPE *peType, BD_BUFFER *pBuff) {
	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket\n"));
	if(pBuff->cSize < PACKET_SIZE_R) {
		IFDBG(DebugOut(DEBUG_ERROR, L"[BCSP] HCI_ReadPacket failed: passed in buffer is too small. ERROR\n"));
		return FALSE;
	}

	while (TRUE) {						// loop through ack packets, link establishment packets,
										// and other packets the client doesn't care about

		IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] In HCI_ReadPacket...\n"));
		BCSPHeader header;
		if (! ReadFromCOMPort(&header, pBuff->pBuffer))
			break;

		if (header.checksum != header.GetChecksum()) {
			IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket: packet checksum is invalid.  Discarding.\n"));
			continue;
		}

		if((header.protocolID == 1) && (header.protocolType == 0) && (header.payloadLength == 4)) {
			const unsigned char syncPayload[] = { 0xDA, 0xDC, 0xED, 0xED };
			const unsigned char confPayload[] = { 0xAD, 0xEF, 0xAC, 0xED };
			if(0 == memcmp(syncPayload, pBuff->pBuffer, 4)) {			// SYNC received so send SYNC-RESP
				IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket : got SYNC scheduling SYNC-RESP.\n"));

				InterlockedIncrement ((LONG *)&g_iRxSyncs);
				SetEvent(g_hWriteThreadEvent);
			} else if(0 == memcmp(confPayload, pBuff->pBuffer, 4)) {		// CONF received so send CONF-RESP
				IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket : got CONF scheduling CONF-RESP.\n"));

				InterlockedIncrement ((LONG *)&g_iRxConfs);
				SetEvent(g_hWriteThreadEvent);
			} else
				IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket : got something strange, discarding...\n"));

			continue;
		}

		if (g_fShutDown)
			break;

		// we now get into the processing stage so enter the critical section
		SVSLocalCriticalSection cs(&g_csBCSP);

		if (g_fShutDown)
			break;

		// For unreliable data there is no need to send an ACK
		if (header.protocolType) {
			// now look for a new ack value to free packets from the transmit window
			if (header.ack != g_iRxAck) {
				IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket : received ACK = %d, scheduling ACK processing\n", header.ack));
				g_iRxAckLast = header.ack;
				SetEvent(g_hWriteThreadEvent);
			}

			// if the packet is a pure ack packet continue
			if (! header.payloadLength) {
				IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket : no payload, ignoring\n"));
				continue;
			}

			if(header.seq == g_iTxAck) {			// this is the sequence number we were expecting
				IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket : packet in sequence, scheduling ACK send\n"));

				g_iTxAck = (g_iTxAck + 1) & BCSP_SEQ_MASK;

				if ((g_iTxUnack++) == 0)
					g_dwTxAckDue = GetTickCount () + BCSP_ACTIVE_TIMEOUT / 2;

				SetEvent(g_hWriteThreadEvent);
			} else {
				IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket : packet out of sequence, scheduling immediate ACK send\n"));

				g_iTxUnack = BCSP_SEQ_MASK + 1;
				g_dwTxAckDue = GetTickCount ();

				SetEvent(g_hWriteThreadEvent);

				continue;			// keep reading
			}
		}

		// the packet has a payload so if it is one that the client wants (ACL data or HCI event) return it
		BOOL success = TRUE;		// return this packet if true after switch

		IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket got a packet.\n"));

		switch(header.protocolID) {

		case IO_DATA_PROTOCOL_NULL:
			IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket got a null ID packet.  Discarding.\n"));
			success = FALSE;
			break;

		case IO_DATA_PROTOCOL_HCI_CMD_EVT:
			IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket got an HCI event packet.\n"));
			*peType = EVENT_PACKET;
			break;

		case IO_DATA_PROTOCOL_HCI_ACL:
			IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket got an ACL data packet.\n"));
			*peType = DATA_PACKET_ACL;
			break;

		case IO_DATA_PROTOCOL_HCI_SCO:
			IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket got a SCO data packet.\n"));
			*peType = DATA_PACKET_SCO;
			break;

		case IO_DATA_PROTOCOL_CHIP_MGT_CH:
			IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket got a chip management packet.\n"));
			success = FALSE;
			break;

		default:
			IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket got some unexepected packet.  Discarding.\n"));
			success = FALSE;
			break;
		}
		
		if (! success)
			continue;			// keep reading for a suitable packet

		pBuff->cEnd = header.payloadLength;
		pBuff->cStart = 0;

		IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] Packet received:\n"));
		IFDBG(DumpBuff (DEBUG_HCI_TRANSPORT, pBuff->pBuffer, pBuff->cEnd));

		return TRUE;
	}

	IFDBG(DebugOut(DEBUG_ERROR, L"[BCSP] HCI_ReadPacket failed. ERROR\n"));
	return FALSE;
}

int HCI_WritePacket (HCI_TYPE eType, BD_BUFFER *pBuff) {
	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_WritePacket\n"));
	IFDBG(DumpBuff (DEBUG_HCI_DUMP, pBuff->pBuffer + pBuff->cStart, BufferTotal (pBuff)));

	// create a packet and set the payload and header flags
	BCSPPacketListNode *pPacketListNode = new BCSPPacketListNode;
	if (! pPacketListNode) {
		IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"HCI_WritePacket: OOM!\n"));
		return FALSE;
	}

	pPacketListNode->packet.SetData(pBuff->pBuffer + pBuff->cStart, BufferTotal (pBuff));	

	if(eType == COMMAND_PACKET) 
		pPacketListNode->packet.header.protocolID = IO_DATA_PROTOCOL_HCI_CMD_EVT;
	else if(eType == DATA_PACKET_ACL)
		pPacketListNode->packet.header.protocolID = IO_DATA_PROTOCOL_HCI_ACL;
	else if(eType == DATA_PACKET_SCO)
		pPacketListNode->packet.header.protocolID = IO_DATA_PROTOCOL_HCI_SCO;

	pPacketListNode->packet.header.crcPresent = 0;
	pPacketListNode->packet.fNewPacket = TRUE;
	pPacketListNode->next = 0;

	// the remaining header fields are filled out by BCSPWriteThread prior to being sent across the wire
	if (pPacketListNode->packet.header.protocolID == IO_DATA_PROTOCOL_HCI_SCO) {
		pPacketListNode->packet.header.protocolType = 0;
		pPacketListNode->packet.header.seq = 0;
		pPacketListNode->packet.header.ack = 0;
	}
	else {
		pPacketListNode->packet.header.protocolType = 1;			// reliable connection type
	}

	// now wait for an empty slot in the transmit queue to open up
	for ( ; ; ) {
		if (g_fShutDown) {
			IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] HCI_WritePacket : shutting down!\n"));
			return FALSE;
		}

		EnterCriticalSection (&g_csBCSP);
		if (g_fShutDown) {
			IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] HCI_WritePacket : shutting down!\n"));
			LeaveCriticalSection (&g_csBCSP);

			return FALSE;
		}

		if (pPacketListNode->packet.header.protocolID == IO_DATA_PROTOCOL_HCI_SCO) {
			if (GetSCOListSize () < BCSP_WIN_SIZE_SCO)
				break;
		}
		else {
			if (GetListSize () < BCSP_WIN_SIZE)
				break;
		}

		IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_WritePacket :: waiting for empty slot...\n"));
		LeaveCriticalSection (&g_csBCSP);

		WaitForSingleObject(g_hCanTransmitPacket, INFINITE);
	}

	AddToList(pPacketListNode);

#ifdef DEBUG
	if (pPacketListNode->packet.header.protocolID == IO_DATA_PROTOCOL_HCI_SCO) {
		IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_WritePacket : SCO Packet added to the list (total %d in list)\n", GetSCOListSize()));
	}
	else {
		IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_WritePacket : Packet added to the list (total %d in list)\n", GetListSize()));
	}
#endif

	SetEvent(g_hWriteThreadEvent);

	LeaveCriticalSection (&g_csBCSP);
	
	return TRUE;
}

⌨️ 快捷键说明

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