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

📄 l2capdev.cxx

📁 Windows CE操作系统中适用的蓝牙驱动程序
💻 CXX
📖 第 1 页 / 共 4 页
字号:
	HANDLE hL2CAP = gpState->hL2CAP;
	L2CA_ConfigReq_In pCallback = gpState->l2cap_if.l2ca_ConfigReq_In;
	gpState->Unlock ();

	int iRes = ERROR_INTERNAL_ERROR;
	__try {
		iRes = pCallback (hL2CAP, pCallContext, cid, mtu, 0xffff, NULL, 0, NULL);
	} __except (1) {
	}

	if (iRes != ERROR_SUCCESS)
		l2capdev_lCallAborted (pCallContext, iRes);

	return ERROR_SUCCESS;
}

static int l2capdev_DataDown_Out (void *pCallContext, unsigned short result) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: Data down call 0x%08x result %d\n", pCallContext, result));
	if (! gpState)
		return ERROR_SERVICE_NOT_ACTIVE;

	gpState->Lock ();

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

	SCall *pCall = VerifyCall ((SCall *)pCallContext);
	if ((! pCall) || pCall->fComplete) {
		gpState->Unlock ();
		return ERROR_NOT_FOUND;
	}

	SVSUTIL_ASSERT (pCall->fWhat == CALL_L2CAP_DATA_WRITE);
	SVSUTIL_ASSERT (! pCall->fComplete);
	SVSUTIL_ASSERT (VerifyLink (pCall->pLink));
	SVSUTIL_ASSERT (! pCall->pBuffer);
	SVSUTIL_ASSERT (! pCall->fAutoClean);

	pCall->iResult = ERROR_SUCCESS;
	pCall->fComplete = TRUE;
	SetEvent (pCall->hEvent);

	gpState->Unlock ();
	return ERROR_SUCCESS;
}

static int l2capdev_Ping_Out (void *pCallContext, BD_ADDR *pba, unsigned char *pOutBuffer, unsigned short size) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: l2capdev_Ping_Out call 0x%08x result %d\n", pCallContext));
	if (! gpState)
		return ERROR_SERVICE_NOT_ACTIVE;

	gpState->Lock ();

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

	SCall *pCall = VerifyCall ((SCall *)pCallContext);
	if ((! pCall) || pCall->fComplete) {
		gpState->Unlock ();
		return ERROR_NOT_FOUND;
	}

	SVSUTIL_ASSERT (pCall->fWhat == CALL_L2CAP_PING);
	SVSUTIL_ASSERT (! pCall->fComplete);
	SVSUTIL_ASSERT (! pCall->pBuffer);
	SVSUTIL_ASSERT (! pCall->fAutoClean);

	pCall->iResult = ERROR_SUCCESS;
	pCall->fComplete = TRUE;

	BD_BUFFER *pBuffer = L2CAP_BufferAlloc (size);
	if (pBuffer)
		memcpy (pBuffer->pBuffer, pOutBuffer, size);

	pCall->pBuffer = pBuffer;
	SetEvent (pCall->hEvent);

	gpState->Unlock ();
	return ERROR_SUCCESS;
}

// These are just stubs - they do nothing
static int l2capdev_ConfigResponse_Out (void *pCallContext, unsigned short result) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: ConfigResponse out call 0x%08x, result %d\n", pCallContext, result));
	return ERROR_SUCCESS;
}

static int l2capdev_ConnectResponse_Out (void *pCallContext, unsigned short result) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: ConnectResponse out call 0x%08x, result %d\n", pCallContext, result));
	return ERROR_SUCCESS;
}

static int l2capdev_Disconnect_Out (void *pCallContext, unsigned short result) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: disconnect out call 0x%08x, result %d\n", pCallContext, result));
	return ERROR_SUCCESS;
}

//
//	Init stuff
//
int l2capdev_CreateDriverInstance (void) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"+l2capdev_CreateDriverInstance\n"));

	if (gpState) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-l2capdev_CreateDriverInstance : ERROR_ALREADY_INITIALIZED\n"));
		return ERROR_ALREADY_INITIALIZED;
	}

	gpState = CreateNewState ();

	if ((! gpState) || (! gpState->fIsRunning)) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-l2capdev_CreateDriverInstance : ERROR_OUTOFMEMORY\n"));
		if (gpState)
			delete gpState;
		gpState = NULL;
		return ERROR_OUTOFMEMORY;
	}

	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-l2capdev_CreateDriverInstance : ERROR_SUCCESS\n"));
	return ERROR_SUCCESS;
}


int l2capdev_CloseDriverInstance (void) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"+l2capdev_CloseDriverInstance\n"));

	if (! gpState) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-l2capdev_CloseDriverInstance : ERROR_SERVICE_NOT_ACTIVE\n"));
		return ERROR_SERVICE_NOT_ACTIVE;
	}

	gpState->Lock ();
	if (! gpState->fIsRunning) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-l2capdev_CloseDriverInstance : ERROR_SERVICE_NOT_ACTIVE\n"));
		gpState->Unlock ();

		return ERROR_SERVICE_NOT_ACTIVE;
	}

	gpState->fIsRunning = FALSE;

	while (gpState->GetRefCount () > 1) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Waiting for ref count in l2capdev_CloseDriverInstance\n"));
		gpState->Unlock ();
		Sleep (200);
		gpState->Lock ();
	}

	while (gpState->pCalls) {
		SetEvent (gpState->pCalls->hEvent);
		gpState->pCalls->iResult = ERROR_CANCELLED;
		gpState->pCalls = gpState->pCalls->pNext;
	}

	while (gpState->pLinks) {
		unsigned short cid = gpState->pLinks->cid;

		gpState->Unlock ();
		gpState->l2cap_if.l2ca_Disconnect_In (gpState->hL2CAP, NULL, cid);
		gpState->Lock ();

		gpState->pLinks = gpState->pLinks->pNext;
	}

	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-l2capdev_CloseDriverInstance : ERROR_SUCCESS\n"));

	gpState->Unlock ();
	delete gpState;
	gpState = NULL;

	return ERROR_SUCCESS;
}

//
//	Main API section
//
int L2CAPConnect
(
BT_ADDR			*pbt,
unsigned short	usPSM,
unsigned short	usInMTU,
unsigned short	*pusCID,
unsigned short	*pusOutMTU
) {
	BD_ADDR *pba = (BD_ADDR *)pbt;
	if (usPSM == 0)
		return ERROR_INVALID_PARAMETER;

	if (! gpState)
		return ERROR_SERVICE_NOT_ACTIVE;

	gpState->Lock ();
	if (! gpState->fIsRunning) {
		gpState->Unlock ();

		return ERROR_SERVICE_NOT_ACTIVE;
	}

	Link *pLink = (Link *)svsutil_GetFixed (gpState->pfmdLinks);
	memset (pLink, 0, sizeof (*pLink));
	pLink->cid = 0;
	pLink->b = *pba;
	pLink->fStage = NONE;
	pLink->hProcOwner = GetOwnerProcess ();
	pLink->inMTU = usInMTU;
	pLink->fIncoming = FALSE;
	pLink->psm = usPSM;

	pLink->pNext = gpState->pLinks;
	gpState->pLinks = pLink;

	SCall *pCall = AllocCall (CALL_L2CAP_LINK_SETUP, pLink, GetOwnerProcess());
	if (! pCall) {
		gpState->Unlock ();
		return ERROR_OUTOFMEMORY;
	}
	
	HANDLE hEvent = pCall->hEvent;
	HANDLE hL2CAP = gpState->hL2CAP;
	L2CA_ConnectReq_In pCallbackConnect = gpState->l2cap_if.l2ca_ConnectReq_In;
	L2CA_ConfigReq_In pCallbackConfig = gpState->l2cap_if.l2ca_ConfigReq_In;
	int iRes = ERROR_INTERNAL_ERROR;
	gpState->Unlock ();
	__try {
		iRes = pCallbackConnect (hL2CAP, pCall, usPSM, pba);
	} __except (1) {
	}

	if (iRes == ERROR_SUCCESS)
		WaitForSingleObject (hEvent, INFINITE);

	if (! gpState)
		return ERROR_SERVICE_NOT_ACTIVE;

	gpState->Lock ();

	if (gpState->fIsRunning) {
		pCall = VerifyCall (pCall);
		pLink = VerifyLink (pLink);
	} else {
		pCall = NULL;
		pLink = NULL;
		iRes = ERROR_SERVICE_NOT_ACTIVE;
	}

	if (iRes == ERROR_SUCCESS) {
		if (pCall && pCall->fComplete)
			iRes = pCall->iResult;
		else
			iRes = ERROR_TIMEOUT;
	}

	if (pCall)
		DeleteCall (pCall);
	else
		iRes = ERROR_INTERNAL_ERROR;

	if ((! pLink) || (pLink->fStage & LINK_ERROR) || (iRes != ERROR_SUCCESS) || (pLink->fStage != UP)) {
		unsigned short cid_disconnect = 0;

		if (pLink) {
			if ((iRes == ERROR_SUCCESS) && (pLink->fStage != UP))
				iRes = ERROR_INTERNAL_ERROR;

			cid_disconnect = pLink->cid;
		} else
			iRes = ERROR_INTERNAL_ERROR;

		gpState->Unlock ();

		if (cid_disconnect)
			L2CAPCloseCID (cid_disconnect);

		return iRes;
	}

	*pusCID = pLink->cid;
	*pusOutMTU = pLink->outMTU;

	gpState->Unlock ();
	return ERROR_SUCCESS;
}

int L2CAPListen
(
unsigned short usPSM,
unsigned short	usInMTU	// =>
) {
	if (usPSM == 0)
		return ERROR_INVALID_PARAMETER;

	if (! gpState)
		return ERROR_SERVICE_NOT_ACTIVE;

	gpState->Lock ();
	if (! gpState->fIsRunning) {
		gpState->Unlock ();

		return ERROR_SERVICE_NOT_ACTIVE;
	}

	HANDLE h = gpState->hL2CAP;
	BT_LAYER_IO_CONTROL pCallback = gpState->l2cap_if.l2ca_ioctl;

	int iRes = ERROR_INTERNAL_ERROR;

	gpState->AddRef ();
	gpState->Unlock ();

	__try {
		int iRet = 0;
		unsigned short usPSMin = usPSM;
		iRes = pCallback (h, BTH_STACK_IOCTL_RESERVE_PORT, sizeof(usPSMin), (char *)&usPSMin, sizeof (usPSM), (char *)&usPSM, &iRet);
	} __except (1) {
	}

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

	if (iRes != ERROR_SUCCESS) {
		gpState->Unlock ();
		return iRes;
	}

	Port *p = gpState->pPorts;
	while (p && (p->psm != usPSM))
		p = p->pNext;

	if (p) {
		gpState->Unlock ();
		return ERROR_ADDRESS_ALREADY_ASSOCIATED;
	}

	p = (Port *)svsutil_GetFixed (gpState->pfmdPorts);
	if (! p) {
		gpState->Unlock ();
		return ERROR_OUTOFMEMORY;
	}

	p->hProcOwner = GetOwnerProcess ();
	p->mtu = usInMTU;
	p->psm = usPSM;
	p->pNext = gpState->pPorts;
	gpState->pPorts = p;

	gpState->Unlock ();
	return ERROR_SUCCESS;
}

int L2CAPAccept
(
unsigned short	usPSM,		// =>
BT_ADDR			*pbt,		// <=
unsigned short	*pusCID,	// <=
unsigned short	*pusOutMTU	// <=
) {
	if (usPSM == 0)
		return ERROR_INVALID_PARAMETER;

	if (! gpState)
		return ERROR_SERVICE_NOT_ACTIVE;

	gpState->Lock ();
	if (! gpState->fIsRunning) {
		gpState->Unlock ();

		return ERROR_SERVICE_NOT_ACTIVE;
	}

	SCall *pCall = gpState->pCalls;
	while (pCall && ((pCall->fWhat != CALL_L2CAP_LINK_SETUP) || (! pCall->fComplete) || (! pCall->pLink) || (pCall->pLink->psm != usPSM) || (! pCall->pLink->fIncoming)))
		pCall = pCall->pNext;

	if (pCall) {
		SVSUTIL_ASSERT (pCall->fAutoClean);
		Link *pLink = pCall->pLink;
		DeleteCall (pCall);
		*pusCID = pLink->cid;
		*pusOutMTU = pLink->outMTU;
		*pbt = SET_NAP_SAP(pLink->b.NAP, pLink->b.SAP);

		gpState->Unlock ();

		return ERROR_SUCCESS;
	}

	Port *p = gpState->pPorts;
	while (p && (p->psm != usPSM))
		p = p->pNext;

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

	pCall = AllocCall (CALL_L2CAP_ACCEPT, NULL, GetOwnerProcess());
	if (! pCall) {
		gpState->Unlock ();
		return ERROR_OUTOFMEMORY;
	}
	
	pCall->psm = usPSM;
	HANDLE hEvent = pCall->hEvent;

	gpState->Unlock ();

	WaitForSingleObject (hEvent, INFINITE);

	if (! gpState)
		return ERROR_SERVICE_NOT_ACTIVE;

	gpState->Lock ();

	if (pCall != VerifyCall (pCall)) {
		gpState->Unlock ();
		return ERROR_CANCELLED;
	}

	Link *pLink = pCall->pLink;
	int iRes = pCall->fComplete ? pCall->iResult : ERROR_TIMEOUT;

	DeleteCall (pCall);

	if (pLink) {
		*pusCID = pLink->cid;
		*pusOutMTU = pLink->outMTU;		
		*pbt = SET_NAP_SAP(pLink->b.NAP, pLink->b.SAP);
	}

	gpState->Unlock ();
	return iRes;
}

int L2CAPClosePSM (unsigned short usPSM) {
	if (usPSM == 0)
		return ERROR_INVALID_PARAMETER;

	if (! gpState)
		return ERROR_SERVICE_NOT_ACTIVE;

	gpState->Lock ();
	if (! gpState->fIsRunning) {
		gpState->Unlock ();

		return ERROR_SERVICE_NOT_ACTIVE;
	}

	Port *pParent = NULL;
	Port *p = gpState->pPorts;
	while (p && (p->psm != usPSM)) {
		pParent = p;
		p = p->pNext;
	}

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

	if (pParent)
		pParent->pNext = p->pNext;
	else
		gpState->pPorts = p->pNext;

	svsutil_FreeFixed (p, gpState->pfmdPorts);

	SCall *pCall = gpState->pCalls;

	while (pCall) {
		if (pCall->psm == usPSM) {
			SVSUTIL_ASSERT (! pCall->fAutoClean);
			SVSUTIL_ASSERT (pCall->fWhat == CALL_L2CAP_ACCEPT);
			SVSUTIL_ASSERT (pCall->hEvent);
			SVSUTIL_ASSERT (pCall->hProcOwner);
			SVSUTIL_ASSERT (! pCall->pBuffer);

			if (! pCall->fComplete) {
				SVSUTIL_ASSERT (! pCall->pLink);
				pCall->fComplete = TRUE;
				pCall->iResult = ERROR_CANCELLED;
				SetEvent (pCall->hEvent);
			}
		}

		pCall = pCall->pNext;
	}

	HANDLE h = gpState->hL2CAP;
	BT_LAYER_IO_CONTROL pCallback = gpState->l2cap_if.l2ca_ioctl;

	int iRes = ERROR_INTERNAL_ERROR;
	gpState->Unlock ();

	__try {
		iRes = pCallback (h, BTH_STACK_IOCTL_FREE_PORT, sizeof(usPSM), (char *)&usPSM, 0, NULL, NULL);
	} __except (1) {
	}

	return iRes;

⌨️ 快捷键说明

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