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

📄 l2capdev.cxx

📁 Windows CE操作系统中适用的蓝牙驱动程序
💻 CXX
📖 第 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.


Abstract:
	Windows CE Bluetooth stack layer sample

**/

#include <windows.h>

#include <svsutil.hxx>

#include <bt_debug.h>
#include <bt_os.h>
#include <bt_buffer.h>
#include <bt_ddi.h>
#include <bt_api.h>

#if defined (UNDER_CE)
#include <pkfuncs.h>
#endif

#include <bt_tdbg.h>

#include "../l2capapi/l2capapi.hxx"
#include "l2capdev.hxx"

#define DEBUG_LAYER_TRACE			0x00000040

DECLARE_DEBUG_VARS();

#define CALL_L2CAP_LINK_SETUP		0x11
#define CALL_L2CAP_ACCEPT			0x12
#define CALL_L2CAP_DATA_WRITE		0x13
#define CALL_L2CAP_DATA_READ		0x14
#define CALL_L2CAP_DISCONNECT		0x15
#define CALL_L2CAP_PING				0x16

#define	NONE			0x00
#define CONNECTED		0x01
#define CONFIG_REQ_DONE 0x02
#define CONFIG_IND_DONE 0x04
#define UP              0x07
#define LINK_ERROR		0x80

struct Link {
	Link			*pNext;
	BD_ADDR			b;
	unsigned short	psm;
	unsigned short	cid;

	unsigned int	fStage;

	unsigned int	fIncoming : 1;

	unsigned short	inMTU;
	unsigned short	outMTU;

	HANDLE			hProcOwner;
};

struct Port {
	Port			*pNext;
	unsigned short	psm;
	unsigned short	mtu;

	HANDLE			hProcOwner;
};

struct SCall {
	SCall			*pNext;
	Link			*pLink;
	HANDLE			hProcOwner;

	HANDLE			hEvent;

	int				iResult;

	unsigned short	psm;

	unsigned int	fWhat			: 8;
	unsigned int	fComplete		: 1;
	unsigned int	fAutoClean		: 1;

	BD_BUFFER		*pBuffer;
};

int l2capdev_CloseDriverInstance (void);

static int l2capdev_ConfigInd (void *pUserContext, unsigned char id, unsigned short cid, unsigned short usOutMTU, unsigned short usInFlushTO, struct btFLOWSPEC *pInFlow, int cOptNum, struct btCONFIGEXTENSION **pExtendedOptions);
static int l2capdev_ConnectInd (void *pUserContext, BD_ADDR *pba, unsigned short cid, unsigned char id, unsigned short psm);
static int l2capdev_DataUpInd (void *pUserContext, unsigned short cid, BD_BUFFER *pBuffer);
static int l2capdev_DisconnectInd (void *pUserContext, unsigned short cid, int iError);
static int l2capdev_lStackEvent (void *pUserContext, int iEvent, void *pEventContext);

static int l2capdev_lCallAborted (void *pCallContext, int iError);
static int l2capdev_ConfigReq_Out (void *pCallContext, unsigned short usResult, unsigned short usInMTU, unsigned short usOutFlushTO, struct btFLOWSPEC *pOutFlow, int cOptNum, struct btCONFIGEXTENSION **pExtendedOptions);
static int l2capdev_ConfigResponse_Out (void *pCallContext, unsigned short result);
static int l2capdev_ConnectReq_Out (void *pCallContext, unsigned short cid, unsigned short result, unsigned short status);
static int l2capdev_ConnectResponse_Out (void *pCallContext, unsigned short result);
static int l2capdev_DataDown_Out (void *pCallContext, unsigned short result);
static int l2capdev_Ping_Out (void *pCallContext, BD_ADDR *pba, unsigned char *pOutBuffer, unsigned short size);
static int l2capdev_Disconnect_Out (void *pCallContext, unsigned short result);

class L2CAPDEV : public SVSSynch, public SVSRefObj {
public:
	Link			*pLinks;
	Port			*pPorts;
	SCall			*pCalls;

	unsigned int	fIsRunning : 1;
	unsigned int	fConnected : 1;

	HANDLE			hL2CAP;
	L2CAP_INTERFACE	l2cap_if;

	int				cHeaders;
	int				cTrailers;

	FixedMemDescr	*pfmdLinks;
	FixedMemDescr	*pfmdPorts;
	FixedMemDescr	*pfmdCalls;

	L2CAPDEV (void) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: new L2CAPDEV\n"));
		pLinks = NULL;
		pPorts = NULL;
		pCalls = NULL;

		cHeaders = 0;
		cTrailers = 0;

		fIsRunning = FALSE;
		fConnected = FALSE;

		hL2CAP = NULL;

		memset (&l2cap_if, 0, sizeof(l2cap_if));

		pfmdLinks = pfmdPorts = pfmdCalls = NULL;

		if (! (pfmdLinks = svsutil_AllocFixedMemDescr (sizeof(Link), 10)))
			return;

		if (! (pfmdPorts = svsutil_AllocFixedMemDescr (sizeof(Port), 10)))
			return;

		if (! (pfmdCalls = svsutil_AllocFixedMemDescr (sizeof(SCall), 10)))
			return;

		L2CAP_EVENT_INDICATION lei;
		memset (&lei, 0, sizeof(lei));

		lei.l2ca_ConfigInd = l2capdev_ConfigInd;
		lei.l2ca_ConnectInd = l2capdev_ConnectInd;
		lei.l2ca_DataUpInd = l2capdev_DataUpInd;
		lei.l2ca_DisconnectInd = l2capdev_DisconnectInd;
		lei.l2ca_StackEvent = l2capdev_lStackEvent;

		L2CAP_CALLBACKS lc;
		memset (&lc, 0, sizeof(lc));

		lc.l2ca_CallAborted = l2capdev_lCallAborted;
		lc.l2ca_ConfigReq_Out = l2capdev_ConfigReq_Out;
		lc.l2ca_ConfigResponse_Out = l2capdev_ConfigResponse_Out;
		lc.l2ca_ConnectReq_Out = l2capdev_ConnectReq_Out;
		lc.l2ca_ConnectResponse_Out = l2capdev_ConnectResponse_Out;
		lc.l2ca_DataDown_Out = l2capdev_DataDown_Out;
		lc.l2ca_Ping_Out = l2capdev_Ping_Out;
		lc.l2ca_Disconnect_Out = l2capdev_Disconnect_Out;

		if (ERROR_SUCCESS != L2CAP_EstablishDeviceContext (this, L2CAP_PSM_MULTIPLE, &lei, &lc, &l2cap_if, &cHeaders, &cTrailers, &hL2CAP))
			return;

		fIsRunning = TRUE;

		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: new L2CAPDEV successful\n"));
	}

	~L2CAPDEV (void) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: delete L2CAPDEV\n"));

		if (hL2CAP)
			L2CAP_CloseDeviceContext (hL2CAP);

		if (pfmdLinks)
			svsutil_ReleaseFixedNonEmpty (pfmdLinks);

		if (pfmdPorts)
			svsutil_ReleaseFixedNonEmpty (pfmdPorts);

		if (pfmdCalls)
			svsutil_ReleaseFixedNonEmpty (pfmdCalls);
	}
};

static L2CAPDEV *gpState = NULL;
//
//	Auxiliary code
//
static L2CAPDEV *CreateNewState (void) {
	return new L2CAPDEV;
}

static SCall *AllocCall (int fWhat, Link *pLink, HANDLE hProcOwner) {
	SCall *pCall = (SCall *)svsutil_GetFixed (gpState->pfmdCalls);
	if (! pCall)
		return NULL;
	
	memset (pCall, 0, sizeof(*pCall));

	pCall->pLink = pLink;
	pCall->hProcOwner = hProcOwner;
	pCall->fWhat = fWhat;

	pCall->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
	if (NULL == pCall->hEvent) {
		svsutil_FreeFixed (pCall, gpState->pfmdCalls);
		return NULL;
	}

	if (! gpState->pCalls)
		gpState->pCalls = pCall;
	else {
		SCall *pLast = gpState->pCalls;
		while (pLast->pNext)
			pLast = pLast->pNext;

		pLast->pNext = pCall;
	}

	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: Allocated call 0x%08x what = 0x%02x\n", pCall, fWhat));

	return pCall;
}

static void DeleteCall (SCall *pCall) {
	if (pCall == gpState->pCalls)
		gpState->pCalls = pCall->pNext;
	else {
		SCall *pParent = gpState->pCalls;
		while (pParent && (pParent->pNext != pCall))
			pParent = pParent->pNext;

		if (! pParent) {
			IFDBG(DebugOut (DEBUG_ERROR, L"Shell: call not in list in DeleteCall!\n"));

			return;
		}

		pParent->pNext = pCall->pNext;
	}

	CloseHandle (pCall->hEvent);

	if (pCall->pBuffer)
		pCall->pBuffer->pFree (pCall->pBuffer);

	svsutil_FreeFixed (pCall, gpState->pfmdCalls);
}

static SCall *VerifyCall (SCall *pCall) {
	SCall *p = gpState->pCalls;
	while (p && (p != pCall))
		p = p->pNext;

#if defined (DEBUG) || defined (_DEBUG) || defined (RETAILLOG)
	if (! p)
		IFDBG(DebugOut (DEBUG_ERROR, L"Shell: call verify failed!\n"));
#endif

	return p;
}

static SCall *FindCall (unsigned int fOp) {
	SCall *p = gpState->pCalls;
	while (p && (p->fWhat != fOp))
		p = p->pNext;

#if defined (DEBUG) || defined (_DEBUG) || defined (RETAILLOG)
	if (! p)
		IFDBG(DebugOut (DEBUG_ERROR, L"Shell: call find failed!\n"));
#endif

	return p;
}

static SCall *FindCall (Link *pLink, unsigned int fOp) {
	SCall *p = gpState->pCalls;
	while (p && ((p->pLink != pLink) || (p->fWhat != fOp)))
		p = p->pNext;

#if defined (DEBUG) || defined (_DEBUG) || defined (RETAILLOG)
	if (! p)
		IFDBG(DebugOut (DEBUG_ERROR, L"Shell: call verify failed!\n"));
#endif

	return p;
}
	
static Link *VerifyLink (Link *pLink) {
	Link *p = gpState->pLinks;
	while (p && (p != pLink))
		p = p->pNext;

#if defined (DEBUG) || defined (_DEBUG) || defined (RETAILLOG)
	if (! p)
		IFDBG(DebugOut (DEBUG_ERROR, L"Shell: link verify failed!\n"));
#endif

	return p;
}

static void DeleteLink (Link *pLink) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: delete link for bd_addr %04x%08x cid 0x%04x\n", pLink->b.NAP, pLink->b.SAP, pLink->cid));

	if (pLink == gpState->pLinks)
		gpState->pLinks = pLink->pNext;
	else {
		Link *pParent = gpState->pLinks;
		while (pParent && (pParent->pNext != pLink))
			pParent = pParent->pNext;

		if (! pParent) {
			IFDBG(DebugOut (DEBUG_ERROR, L"Shell: link to be deleted not in list\n"));
			return;
		}

		pParent->pNext = pLink->pNext;
	}

	SCall *pC = gpState->pCalls;
	while (pC) {
		if (pC->pLink == pLink) {
			if (pC->fAutoClean) {
				DeleteCall (pC);
				pC = gpState->pCalls;
				continue;
			} else if (! pC->fComplete) {
				pC->pLink = NULL;
				pC->fComplete = TRUE;
				pC->iResult = ERROR_CONNECTION_UNAVAIL;
				SetEvent (pC->hEvent);
			} else {
				pC->pLink = NULL;
				if (pC->iResult == ERROR_SUCCESS)
					pC->iResult = ERROR_CONNECTION_UNAVAIL;

			}
		}

		pC = pC->pNext;
	}

	svsutil_FreeFixed (pLink, gpState->pfmdLinks);
}

static Link *FindLink (unsigned short cid) {
	Link *p = gpState->pLinks;
	while (p && (p->cid != cid))
		p = p->pNext;

#if defined (DEBUG) || defined (_DEBUG) || defined (RETAILLOG)
	if (! p)
		IFDBG(DebugOut (DEBUG_ERROR, L"Shell: Link not found for cid 0x%04x\n", cid));
#endif

	return p;
}

static void L2CAP_BufferFree (BD_BUFFER *pBuf) {
	if (! pBuf->fMustCopy)
		g_funcFree (pBuf, g_pvFreeData);
}

static BD_BUFFER *L2CAP_BufferAlloc (int cSize) {
	SVSUTIL_ASSERT (cSize > 0);

	BD_BUFFER *pRes = (BD_BUFFER *)g_funcAlloc (cSize + sizeof (BD_BUFFER), g_pvAllocData);
	pRes->cSize = cSize;

	pRes->cEnd = pRes->cSize;
	pRes->cStart = 0;

	pRes->fMustCopy = FALSE;
	pRes->pFree = L2CAP_BufferFree;
	pRes->pBuffer = (unsigned char *)(pRes + 1);

	return pRes;
}

static BD_BUFFER *L2CAP_BufferCopy (BD_BUFFER *pBuffer) {
	BD_BUFFER *pRes = L2CAP_BufferAlloc (pBuffer->cSize);
	pRes->cSize = pBuffer->cSize;
	pRes->cStart = pBuffer->cStart;
	pRes->cEnd = pBuffer->cEnd;
	pRes->fMustCopy = FALSE;
	pRes->pFree = L2CAP_BufferFree;
	pRes->pBuffer = (unsigned char *)(pRes + 1);

	memcpy (pRes->pBuffer, pBuffer->pBuffer, pRes->cSize);

	return pRes;
}

static DWORD WINAPI StackDown (LPVOID lpVoid) {		// Attention - must increment ref count before calling this!
	if (! gpState)
		return ERROR_SERVICE_NOT_ACTIVE;

	gpState->Lock ();
	gpState->DelRef ();

	if ((! gpState->fIsRunning) || (! gpState->fConnected)) {
		gpState->Unlock ();

		return ERROR_SERVICE_NOT_ACTIVE;
	}

	gpState->fConnected = FALSE;

    Link *pLink = gpState->pLinks;

	while (gpState->pLinks)
		DeleteLink (gpState->pLinks);

	SCall *pC = gpState->pCalls;
	while (pC) {
		if (pC->fWhat != CALL_L2CAP_ACCEPT) {
			if (pC->fAutoClean) {
				DeleteCall (pC);
				pC = gpState->pCalls;
				continue;
			} else if (! pC->fComplete) {
				pC->pLink = NULL;
				pC->fComplete = TRUE;
				pC->iResult = ERROR_CONNECTION_UNAVAIL;
				SetEvent (pC->hEvent);
			} else {
				pC->pLink = NULL;
				if (pC->iResult == ERROR_SUCCESS)
					pC->iResult = ERROR_CONNECTION_UNAVAIL;

			}
		}

		pC = pC->pNext;
	}

	gpState->Unlock ();
	return ERROR_SUCCESS;
}

static DWORD WINAPI StackUp (LPVOID lpVoid) {	// Attention - must increment ref count before calling this!
	if (! gpState)
		return ERROR_SERVICE_NOT_ACTIVE;

	gpState->Lock ();
	gpState->DelRef ();

	if ((! gpState->fIsRunning) || gpState->fConnected) {
		gpState->Unlock ();

		return ERROR_SERVICE_NOT_ACTIVE;
	}

	gpState->fConnected = TRUE;
	gpState->Unlock ();

	return ERROR_SUCCESS;
}

static void ProcessExited (HANDLE hProc) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: ProcessExited 0x%08x\n", hProc));

	if (! gpState)
		return;

	gpState->Lock ();

	if (! gpState->fIsRunning) {
		gpState->Unlock ();
		return;
	}


    Port *pPort = gpState->pPorts;

	while (pPort) {
		if (pPort->hProcOwner == hProc) {
			unsigned short psm = pPort->psm;

⌨️ 快捷键说明

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