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

📄 hcibcsp.cpp

📁 Windows CE操作系统中适用的蓝牙驱动程序
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Module Name:  

    hcibcsp.cpp

Abstract:  

Implementation of BCSP protocol
    
Functions:


Notes:

--*/

//#define LOCALDBG	L"bcsp"
//#define FULL_BCSP_DUMP	1
#define BT_USE_CELOG		1

#include <windows.h>
#include <bt_hcip.h>			// implement the functions declared here
#include <bt_debug.h>
#include <bt_tdbg.h>
#include <svsutil.hxx>
#include <bt_os.h>

#define DEFAULT_WORKER_THREAD_PRIORITY	132

#if defined (SDK_BUILD) && defined (BT_USE_CELOG)
#define CELOGSDK_FILELOG	L"bcsp"
#define CELOGSDK_DEFINE		1

#include "../../../../../../../../private/osinternal/pbtools/privdbg/celog_sdk.h"
#endif

// uncomment this line if using a card that does not support BCSP link establishment

// #define BCSP_NO_LINK_ESTABLISHMENT

// these are the possible values of the Protocol ID field of the BCSP Header and their meanings

#define   IO_DATA_PROTOCOL_NULL          0 /* Null protocol            */
#define   IO_DATA_PROTOCOL_LINK_MGT      1 /* Link Management          */
#define   IO_DATA_PROTOCOL_CHIP_MGT_HC   2 /* CSR Chip Mgt Host/Chip   */
#define   IO_DATA_PROTOCOL_CHIP_MGT_CH   3 /* CSR Chip Mgt Chip/Host   */
#define   IO_DATA_PROTOCOL_DEVICE_MGT    4 /* Device Manager           */
#define   IO_DATA_PROTOCOL_HCI_CMD_EVT   5 /* HCI Command or Event     */
#define   IO_DATA_PROTOCOL_HCI_ACL       6 /* HCI ACL Data             */
#define   IO_DATA_PROTOCOL_HCI_SCO       7 /* HCI SCO Data             */
#define   IO_DATA_PROTOCOL_L2CAP         8 /* L2CAP API Transport      */
#define   IO_DATA_PROTOCOL_RFCOMM        9 /* RFCOMM API Transport     */
#define   IO_DATA_PROTOCOL_SDD          10 /* SDP API Transport        */
#define   IO_DATA_PROTOCOL_RSVD_ID_11   11 
#define   IO_DATA_PROTOCOL_RSVD_ID_12   12
#define   IO_DATA_PROTOCOL_RSVD_ID_13   13
#define   IO_DATA_PROTOCOL_RSVD_ID_14   14
#define   IO_DATA_PROTOCOL_RSVD_ID_15   15

#define SLIP_END		0xc0
#define SLIP_ESC		0xdb
#define SLIP_ESC_END	0xdc
#define SLIP_ESC_ESC	0xdd

#define SLIP_BUFFER_SIZE	256

#define BCSP_RETRY_LIMIT		20
#define BCSP_ACTIVE_TIMEOUT		250
#define BCSP_PASSIVE_TIMEOUT	1000
#define BCSP_SEQ_MASK			7
#define BCSP_WIN_SIZE			4
#define BCSP_WIN_SIZE_SCO		4

#define PACKET_SIZE_R		(4095 * 2 + 8)
#define PACKET_SIZE_W		(4095 * 2 + 8)

#define MAX_BUFFER_SIZE		(PACKET_SIZE_W * 2)

#define DEFAULT_COM_NAME	L"COM1:"

#define DEBUG_READ_BUFFER_HEADER	4
#define DEBUG_WRITE_BUFFER_HEADER	8
#define DEBUG_READ_BUFFER_TRAILER	1
#define DEBUG_WRITE_BUFFER_TRAILER	3

#define SCO_DEFAULT_SAMPLE_SIZE				8
#define SCO_DEFAULT_WRITE_LOW_NUM_PACKETS	2
#define SCO_DEFAULT_WRITE_HIGH_NUM_PACKETS	4
#define SCO_DEFAULT_PACKET_SIZE				51


DECLARE_DEBUG_VARS();

#pragma pack(push, 1)
struct BCSPHeader {
	union {
		unsigned char flags;
		struct {
			unsigned char seq : 3;
			unsigned char ack : 3;
			unsigned char crcPresent : 1;
			unsigned char protocolType : 1;
		};
	};
	struct {
		unsigned short protocolID : 4;
		unsigned short payloadLength : 12;
	};
	unsigned char checksum;

	unsigned char GetChecksum (void) {
		const unsigned char *pThis = (unsigned char *)this;
		return ~(pThis[0] + pThis[1] + pThis[2]);
	}

	void SetChecksum (void) {
		checksum = GetChecksum();
	}
};
#pragma pack(pop)

class BCSPPacket {
	unsigned char *pPacketData;					// pPayloadData is entire SLIP-encoded packet
												// length of pPacketData is 10 + slipPayloadLength

	int slipPayloadLength;				// slipPayloadLength is length of SLIP-encoded payload

public:
	BCSPHeader header;

	unsigned int fNewPacket : 1;								// if true, packet has not yet been sent
	unsigned int fResendPacket : 1;								// if true, packet has not yet been re-sent
		
	void	SetData(const void *, int);
	int		WriteToCOMPort (int fUnlock);

	BCSPPacket (void) {
		memset (this, 0, sizeof(*this));
	}

	~BCSPPacket (void) {
		if(pPacketData)
			free (pPacketData);
	}
};

struct BCSPPacketListNode {
	BCSPPacket					packet;
	BCSPPacketListNode			*next;
};

struct SerialPacket {
	SerialPacket	*pNext;

	int				cSize;
	int				cOffset;
	unsigned char	ucbuffer[1024];
};
//
//	Globals and their maintenance
//
static HANDLE hFile = INVALID_HANDLE_VALUE;					// handle to BCSP device
static HCI_TransportCallback gCallback = NULL;

static CRITICAL_SECTION		g_csBCSP;

static HANDLE				g_hWriteThreadEvent;
static HANDLE				g_hWriteThread;
static HANDLE				g_hCanTransmitPacket;	// signaled if transmit window has empty space and choke is off

static int					g_iTxSeq;       // sequence number of next packet to be transmitted
static int					g_iTxAck;       // ack number of next packet to be transmitted
                                            // this equals sequence number of last packet received plus one
                                            // g_iTxAck equals rxSeq at all times

static int					g_iRxAck;       // last processed acknowledgement received
static int					g_iRxAckLast;   // last unprocessed acknowledgement received

static int                  g_iRxSyncs;     // Number of received sync packets
static int                  g_iRxConfs;     // Number of received sync packets

static int					g_iTxUnack;     // How many packets not acked
static DWORD				g_dwTxAckDue;   // When the next ack is due

static DWORD				g_dwScoSampleSize;	// Size in bits of SCO samples (e.g. 8 or 16)

static BCSPPacketListNode   *g_pTransmitPackets = 0;
static BCSPPacketListNode   *g_pSCOTransmitPackets = 0;

static int					g_fShutDown = FALSE;

static int              g_fSerialError;
static CRITICAL_SECTION g_csPackets;
static SerialPacket     *g_pPackets;
static FixedMemDescr    *g_pfmdPacketDescr;
static HANDLE           g_hPacketReady;
static HANDLE           g_hReadThread;

static int				g_fCeLog = FALSE;

static void ReinitGlobals (void) {
	g_hWriteThreadEvent = NULL;
	g_hWriteThread = NULL;
	g_hReadThread = NULL;
	g_hPacketReady = NULL;
	g_hCanTransmitPacket = NULL;

	g_iTxSeq = 0;
	g_iTxAck = 0;

	g_iTxUnack   = 0;
	g_dwTxAckDue = 0;

	g_iRxAck = 0;
	g_iRxAckLast = 0;

	g_iRxSyncs = 0;
	g_iRxConfs = 0;

	g_pTransmitPackets = NULL;
	g_pSCOTransmitPackets = NULL;

	g_fSerialError = FALSE;
	g_pPackets = NULL;
	g_pfmdPacketDescr = NULL;
}
	
//
//	Serial IO functions
//
static int WriteCommPort (unsigned char *pBuffer, DWORD dwLen) {
	DWORD dwFilledSoFar = 0;
	while (dwFilledSoFar < dwLen) {
		DWORD dwWrit = 0;
		if ((! WriteFile (hFile, &pBuffer[dwFilledSoFar], dwLen - dwFilledSoFar, &dwWrit, NULL)) &&
			(dwWrit == 0)) {
			if (hFile != INVALID_HANDLE_VALUE) {
				IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] Error writing COM port: GetLastError = 0x%08x (%d)\n", GetLastError (), GetLastError ()));
			}
			return FALSE;
		}

#if defined (BT_USE_CELOG)
		if (g_fCeLog) {
			CELOGDATAFLAGGED(TRUE, CELID_RAW_UCHAR, &pBuffer[dwFilledSoFar], (unsigned short)dwWrit, 0, CELZONE_ALWAYSON, CELOG_FLAG_RAW_OUT);
		}
#endif
		dwFilledSoFar += dwWrit;
	}

	return TRUE;
}

static DWORD WINAPI COMReadThread (LPVOID phandles) {
	PurgeComm (hFile, PURGE_RXCLEAR);

	if (! SetCommMask (hFile, EV_RXCHAR)) {
		g_fSerialError = TRUE;
		SetEvent (g_hPacketReady);
		IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] Failed SetCommMask in BCSP HCI Interface. GetLastError = 0x%08x\n", GetLastError ()));
		return FALSE;
    }

	EnterCriticalSection (&g_csPackets);
	SerialPacket *pPacket = ((! g_fShutDown) && g_pfmdPacketDescr) ? (SerialPacket *)svsutil_GetFixed (g_pfmdPacketDescr) : NULL;
	LeaveCriticalSection (&g_csPackets);

	for ( ; ; ) {
		DWORD dwEvent = 0;
		if (! WaitCommEvent (hFile, &dwEvent, NULL)) {
			if (hFile != INVALID_HANDLE_VALUE) {
				g_fSerialError = TRUE;
				IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] Error waiting on COM port: GetLastError = 0x%08x (%d)\n", GetLastError (), GetLastError ()));
			}

			SetEvent (g_hPacketReady);
			return FALSE;
		}

		if (! SetCommMask (hFile, EV_RXCHAR)) {
			if (hFile != INVALID_HANDLE_VALUE) {
				g_fSerialError = TRUE;
				IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] Failed SetCommMask in BCSP HCI Interface. GetLastError = 0x%08x\n", GetLastError ()));
			}

			SetEvent (g_hPacketReady);
			return FALSE;
		}

		if ((dwEvent & EV_RXCHAR) == 0)
			continue;

		EnterCriticalSection (&g_csPackets);
		if (! pPacket)
			pPacket = ((! g_fShutDown) && g_pfmdPacketDescr) ? (SerialPacket *)svsutil_GetFixed (g_pfmdPacketDescr) : NULL;
		LeaveCriticalSection (&g_csPackets);

		if (! pPacket) {
			g_fSerialError = TRUE;
			SetEvent (g_hPacketReady);
			IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] OOM in COMPortReadThread. GetLastError = 0x%08x\n", GetLastError ()));
			return FALSE;
		}

		if ((! ReadFile (hFile, pPacket->ucbuffer, sizeof(pPacket->ucbuffer), (DWORD *)&pPacket->cSize, NULL)) &&
			(pPacket->cSize == 0)) {
			EnterCriticalSection (&g_csPackets);
			if ((! g_fShutDown) && g_pfmdPacketDescr)
				svsutil_FreeFixed (pPacket, g_pfmdPacketDescr);
			LeaveCriticalSection (&g_csPackets);

			if (hFile != INVALID_HANDLE_VALUE) {
				g_fSerialError = TRUE;
				IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] Error reading COM port: GetLastError = 0x%08x (%d)\n", GetLastError (), GetLastError ()));
			}

			SetEvent (g_hPacketReady);
			return FALSE;
		}

		if (pPacket->cSize) {
#if defined (FULL_BCSP_DUMP)
			IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[BCSP] Bytes arrived:\n"));
			IFDBG(DumpBuff (DEBUG_HCI_TRANSPORT, pPacket->ucbuffer, pPacket->cSize));
#endif
#if defined (BT_USE_CELOG)
			if (g_fCeLog) {
				CELOGDATAFLAGGED(TRUE, CELID_RAW_UCHAR, pPacket->ucbuffer, pPacket->cSize, 0, CELZONE_ALWAYSON, CELOG_FLAG_RAW_IN);
			}
#endif
			pPacket->cOffset = 0;

			EnterCriticalSection (&g_csPackets);

			pPacket->pNext = NULL;

			if (! g_pPackets)
				g_pPackets = pPacket;
			else {
				SerialPacket *pRunner = g_pPackets;
				while (pRunner->pNext)
					pRunner = pRunner->pNext;
				pRunner->pNext = pPacket;
			}

			SetEvent (g_hPacketReady);
			LeaveCriticalSection (&g_csPackets);

			pPacket = NULL;
		}
	}
}

static int PushBackData (unsigned char *pBuffer, DWORD dwLen) {
	SerialPacket *pPacket = (SerialPacket *)svsutil_GetFixed (g_pfmdPacketDescr);
	if (! pPacket) {
		g_fSerialError = TRUE;
		SetEvent (g_hPacketReady);
		IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] OOM in PushBackData. GetLastError = 0x%08x\n", GetLastError ()));
		return FALSE;
	}

	pPacket->cSize = dwLen;
	pPacket->cOffset = 0;
	memcpy(pPacket->ucbuffer, pBuffer, dwLen);

	pPacket = g_pPackets;
	g_pPackets = pPacket;

	return TRUE;
}

static int ReadCommPort (unsigned char *pBuffer, DWORD dwLen) {
	DWORD dwFilledSoFar = 0;
	while (dwFilledSoFar < dwLen) {
		EnterCriticalSection (&g_csPackets);
		if (g_fShutDown || (hFile == INVALID_HANDLE_VALUE) || g_fSerialError) {
			IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] Error reading COM port (or closed) - bailing out.\n"));
			LeaveCriticalSection (&g_csPackets);
			return FALSE;
		}

		while (g_pPackets && (dwFilledSoFar < dwLen)) {
			SVSUTIL_ASSERT (g_pPackets->cOffset < g_pPackets->cSize);
			DWORD dwRead = g_pPackets->cSize - g_pPackets->cOffset;
			if (dwRead > (dwLen - dwFilledSoFar))
				dwRead = dwLen - dwFilledSoFar;

			memcpy (pBuffer + dwFilledSoFar, g_pPackets->ucbuffer + g_pPackets->cOffset, dwRead);
			g_pPackets->cOffset += dwRead;
			dwFilledSoFar += dwRead;

			if (g_pPackets->cOffset == g_pPackets->cSize) {
				SerialPacket *pNext = g_pPackets->pNext;
				svsutil_FreeFixed (g_pPackets, g_pfmdPacketDescr);
				g_pPackets = pNext;
			}
		}

		LeaveCriticalSection (&g_csPackets);

		if (dwFilledSoFar < dwLen)
			WaitForSingleObject (g_hPacketReady, INFINITE);
	}

	return TRUE;
}

static void CloseCommPort (void) {
	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] CloseCommPort\n"));

	if (hFile != INVALID_HANDLE_VALUE) {
#if defined (BT_USE_CELOG)
		if (g_fCeLog) {
			BTH_CELOG_STOP_DATA sd;
			GetLocalTime (&sd.st);

			CELOGDATAFLAGGED(TRUE, CELID_RAW_UCHAR, &sd, sizeof(sd), 0, CELZONE_ALWAYSON, CELOG_FLAG_STOP);

#if defined (SDK_BUILD)
			CELOGSDK_STOP ();
#endif

			g_fCeLog = FALSE;
		}

⌨️ 快捷键说明

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