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

📄 l2cap.cxx

📁 三星2440原版bsp
💻 CXX
📖 第 1 页 / 共 5 页
字号:
static DWORD WINAPI CallTimeout (LPVOID pArg) {
	IFDBG(DebugOut (DEBUG_L2CAP_TRACE, L"CallTimeout\n"));

	if (! gpL2CAP) {
		IFDBG(DebugOut (DEBUG_L2CAP_TRACE, L"CallTimeout : shutting down!\n"));
		return 0;
	}

	gpL2CAP->Lock ();

	if (gpL2CAP->eStage != Connected) {
		IFDBG(DebugOut (DEBUG_L2CAP_TRACE, L"CallTimeout : shutting down!\n"));
		gpL2CAP->Unlock ();
		return 0;
	}

	CallContext *pCall = VerifyCall ((CallContext *)pArg);
	if (! pCall) {
		IFDBG(DebugOut (DEBUG_L2CAP_TRACE, L"CallTimeout : no call!\n"));
		gpL2CAP->Unlock ();
		return 0;
	}

	if (pCall->dwTimeOutCookie != 0) {
		IFDBG(DebugOut (DEBUG_L2CAP_TRACE, L"CallTimeout : timeouting the call\n"));

		pCall->dwTimeOutCookie = 0;

		if (pCall->eWhat == CALL_LOG_DISCONNECT_REQ) {
			SVSUTIL_ASSERT (VerifyLog (pCall->u.pLogLink));

			LogLink *pLog = pCall->u.pLogLink;

			CancelCall (pCall, ERROR_TIMEOUT);

			if (VerifyLog (pLog))
				DisconnectLogicalLink (pLog, ERROR_TIMEOUT, FALSE);
		} else if (pCall->eWhat == CALL_PHYS_PING) {
			SVSUTIL_ASSERT (VerifyPhys (pCall->u.pPhysLink));

			PhysLink *pPhys = pCall->u.pPhysLink;

			CancelCall (pCall, ERROR_TIMEOUT);

			if (VerifyPhys (pPhys))
				DisconnectPhysicalLink (pPhys, FALSE, ERROR_TIMEOUT, NULL);
		} else
			SVSUTIL_ASSERT (0);
	}

	IFDBG(DebugOut (DEBUG_L2CAP_TRACE, L"CallTimeout : done\n"));
	gpL2CAP->Unlock ();
	return 0;
}


static void ScheduleTimeout (PhysLink *pLink, DWORD dwTime) {
	if (pLink->dwTimeOutCookie)
		btutil_UnScheduleEvent (pLink->dwTimeOutCookie);

	pLink->dwTimeOutCookie = btutil_ScheduleEvent (PhysLinkTimeout, pLink, dwTime * 1000);
}

static void ScheduleTimeout (LogLink *pLink, DWORD dwTime) {
	if (pLink->dwTimeOutCookie)
		btutil_UnScheduleEvent (pLink->dwTimeOutCookie);

	pLink->dwTimeOutCookie = btutil_ScheduleEvent (LogLinkTimeout, pLink, dwTime * 1000);
}

static void ScheduleTimeout (CallContext *pCall, DWORD dwTime) {
	if (pCall->dwTimeOutCookie)
		btutil_UnScheduleEvent (pCall->dwTimeOutCookie);

	pCall->dwTimeOutCookie = btutil_ScheduleEvent (CallTimeout, pCall, dwTime * 1000);
}

static void UnscheduleTimeout (PhysLink *pLink) {
	if (pLink->dwTimeOutCookie)
		btutil_UnScheduleEvent (pLink->dwTimeOutCookie);
	pLink->dwTimeOutCookie = 0;
}

static void UnscheduleTimeout (LogLink *pLink) {
	if (pLink->dwTimeOutCookie)
		btutil_UnScheduleEvent (pLink->dwTimeOutCookie);
	pLink->dwTimeOutCookie = 0;
}

static void UnscheduleTimeout (CallContext *pCall) {
	if (pCall->dwTimeOutCookie)
		btutil_UnScheduleEvent (pCall->dwTimeOutCookie);
	pCall->dwTimeOutCookie = 0;
}

//
//	Communicate stack event up
//
static void DispatchStackEvent (int iEvent) {
	L2CAP_CONTEXT *pContext = gpL2CAP->pContexts;
	while (pContext && gpL2CAP->IsStackRunning ()) {
		BT_LAYER_STACK_EVENT_IND pCallback = pContext->ei.l2ca_StackEvent;
		if (pCallback) {
			void *pUserContext = pContext->pUserContext;

			IFDBG(DebugOut (DEBUG_L2CAP_CALLBACK, L"Going into StackEvent notification\n"));
			pContext->AddRef ();
			gpL2CAP->Unlock ();

			__try {
				pCallback (pUserContext, iEvent, NULL);
			} __except (1) {
				IFDBG(DebugOut (DEBUG_ERROR, L"[L2CAP] L2CAP_connect_transport: exception in L2CAP_StackEvent!\n"));
			}

			gpL2CAP->Lock ();
			pContext->DelRef ();
			IFDBG(DebugOut (DEBUG_L2CAP_CALLBACK, L"Came back StackEvent notification\n"));
		}
		pContext = pContext->pNext;
	}
}

static DWORD WINAPI StackDown (LPVOID pArg) {
	IFDBG(DebugOut (DEBUG_L2CAP_TRACE, L"Disconnect stack\n"));

	for ( ; ; ) {
		if (! gpL2CAP) {
			IFDBG(DebugOut (DEBUG_ERROR, L"[L2CAP] DisconnectStack:: ERROR_SERVICE_DOES_NOT_EXIST\n"));
			return ERROR_SERVICE_DOES_NOT_EXIST;
		}

		gpL2CAP->Lock ();
		if (gpL2CAP->eStage != Connected) {
			IFDBG(DebugOut (DEBUG_ERROR, L"[L2CAP] DisconnectStack:: ERROR_SERVICE_ALREADY_RUNNING\n"));
			gpL2CAP->Unlock ();
			return ERROR_SERVICE_ALREADY_RUNNING;
		}
		if (gpL2CAP->GetRefCount () == 1)
			break;

		IFDBG(DebugOut (DEBUG_L2CAP_TRACE, L"Waiting for ref count in StackDown\n"));
		gpL2CAP->Unlock ();
		Sleep (100);
	}

	gpL2CAP->iEchoes = 0;
	gpL2CAP->eStage = Disconnected;
	gpL2CAP->AddRef ();

	while (gpL2CAP->pPhysLinks && gpL2CAP->IsStackRunning ()) {
		gpL2CAP->pPhysLinks->eStage = DISCONNECTED;
		DisconnectPhysicalLink (gpL2CAP->pPhysLinks, FALSE, ERROR_SHUTDOWN_IN_PROGRESS, NULL);
	}

	while (gpL2CAP->pCalls && gpL2CAP->IsStackRunning ())
		AbortCall (gpL2CAP->pCalls, ERROR_SHUTDOWN_IN_PROGRESS);

	DispatchStackEvent (BTH_STACK_DOWN);

	gpL2CAP->DelRef ();

	IFDBG(DebugOut (DEBUG_L2CAP_TRACE, L"DisconnectStack:: ERROR_SUCCESS\n"));
	gpL2CAP->Unlock ();

	return ERROR_SUCCESS;
}

static DWORD WINAPI StackUp (LPVOID pArg) {
	IFDBG(DebugOut (DEBUG_L2CAP_TRACE, L"Connect stack\n"));

	for ( ; ; ) {
		if (! gpL2CAP) {
			IFDBG(DebugOut (DEBUG_ERROR, L"[L2CAP] ConnectStack:: ERROR_SERVICE_DOES_NOT_EXIST\n"));
			return ERROR_SERVICE_DOES_NOT_EXIST;
		}

		gpL2CAP->Lock ();
		if (gpL2CAP->eStage != Disconnected) {
			IFDBG(DebugOut (DEBUG_ERROR, L"[L2CAP] ConnectStack:: ERROR_SERVICE_ALREADY_RUNNING\n"));
			gpL2CAP->Unlock ();
			return ERROR_SERVICE_ALREADY_RUNNING;
		}
		if (gpL2CAP->GetRefCount () == 1)
			break;

		IFDBG(DebugOut (DEBUG_L2CAP_TRACE, L"Waiting for ref count in StackUp\n"));
		gpL2CAP->Unlock ();
		Sleep (100);
	}

	gpL2CAP->AddRef ();

	gpL2CAP->eStage = Connected;

	SetScanEnable ();

	DispatchStackEvent (BTH_STACK_UP);

	gpL2CAP->DelRef ();

	IFDBG(DebugOut (DEBUG_L2CAP_TRACE, L"ConnectStack:: ERROR_SUCCESS\n"));
	gpL2CAP->Unlock ();

	return ERROR_SUCCESS;
}

static DWORD WINAPI StackReset (LPVOID pArg) {
	IFDBG(DebugOut (DEBUG_L2CAP_TRACE, L"Reset stack\n"));

	StackDown (NULL);
	StackUp (NULL);

	return NULL;
}

static DWORD WINAPI StackDisconnect (LPVOID pArg) {
	IFDBG(DebugOut (DEBUG_L2CAP_TRACE, L"Disconnect stack\n"));

	l2cap_CloseDriverInstance ();

	return NULL;
}

static BOOL IsModeChangeEvent (unsigned char *p, int c) {
	if ((c >= 8)                        &&  // Ensure size is large enough to be a mode change
		(p[0] == HCI_Mode_Change_Event) &&  // Is a mode change
		(p[2] == 0))                        // Status of mode change is success
	{
		return TRUE;
	}

	return FALSE;
}

static void UnParkIfNeeded (PhysLink* pPhysLink) {
	if (pPhysLink->mode == 0x03) {
		BT_ADDR bta = SET_NAP_SAP(pPhysLink->b.NAP, pPhysLink->b.SAP);
		BthExitParkMode (&bta);
	}
}


//
//	The MEAT
//
static void AbortCall (CallContext *pCall, int iErr) {
	pCall->fComplete = TRUE;
	pCall->iResult = iErr;

	int fDel = ! pCall->fKeepOnAbort;

	if (pCall->eType == CALL_CTX_EVENT) {
		SetEvent (pCall->hEvent);
	} else if (pCall->eType == CALL_CTX_CALLBACK) {
		__try {
			pCall->pCallback (pCall, iErr);
		} __except (1) {
			IFDBG(DebugOut (DEBUG_ERROR, L"CALL_CTX_CALLBACK :: Excepted in AbortCall while processing callbacl\n"));
		}
	} else if (pCall->eType == CALL_CTX_CALLOWNER) {
		L2CAP_CONTEXT *pContext = VerifyContext (pCall->pOwner);
		if (pContext && pContext->c.l2ca_CallAborted) {
			BT_LAYER_CALL_ABORTED pCallback = pContext->c.l2ca_CallAborted;
			void *pCallContext = pCall->pContext;
			pContext->AddRef ();
			IFDBG(DebugOut (DEBUG_L2CAP_CALLBACK, L"AbortCall:: going in callback\n"));
			gpL2CAP->Unlock ();
			__try {
				pCallback (pCallContext, iErr);
			} __except (1) {
				IFDBG(DebugOut (DEBUG_ERROR, L"CALL_CTX_CALLOWNER :: Excepted in AbortCall while processing callbacl\n"));
			}
			gpL2CAP->Lock ();
			IFDBG(DebugOut (DEBUG_L2CAP_CALLBACK, L"AbortCall:: back from callback\n"));
			pContext->DelRef ();
		}
	} else if (pCall->eType == CALL_CTX_INTERNAL)
		;
	else
		SVSUTIL_ASSERT (0);

	if (fDel && gpL2CAP->IsStackRunning ())
		DeleteCallContext (pCall);
}

static void DisconnectLogicalLink (LogLink *pThis, int iErr, int fSendDisconnect) {
	//	Take it out of the list
	if (! PluckLogLink (pThis)) {
		IFDBG(DebugOut (DEBUG_ERROR, L"Disconnecting non-existent link!\n"));
		return;
	}

	UnscheduleTimeout (pThis);

	if (! pThis->pPhysLink->pLogLinks)
		ScheduleTimeout (pThis->pPhysLink, gpL2CAP->dwPhysIdle);

	CallContext *pCall;
	//	Cancel all calls to it...
	while ((gpL2CAP->IsStackRunning ()) && (pCall = FindCall (pThis)))
		AbortCall (pCall, iErr);

	if (! gpL2CAP->IsStackRunning ())
		return;

	unsigned short cid = pThis->cid;
	unsigned short cid_remote = pThis->cid_remote;
	unsigned short h = (pThis->pPhysLink && (pThis->pPhysLink->eStage == UP)) ? pThis->pPhysLink->h : BT_HCI_INVALID_HANDLE;
	
	L2CAP_CONTEXT *pOwner = VerifyContext (pThis->pOwner);
	// Delete the thing.
	delete pThis;

	//	Signal disconnection, if required
	if (cid && pOwner && pOwner->ei.l2ca_DisconnectInd) {
		IFDBG(DebugOut (DEBUG_L2CAP_TRACE, L"DisconnectLogicalLink :: closing cid 0x%04x\n", cid));
		IFDBG(DebugOut (DEBUG_L2CAP_CALLBACK, L"DisconnectLogicalLink:: going into callback\n"));

		pOwner->AddRef ();
		gpL2CAP->Unlock ();

		__try {
			pOwner->ei.l2ca_DisconnectInd (pOwner->pUserContext, cid, iErr);
		} __except (1) {
			IFDBG(DebugOut (DEBUG_ERROR, L"DisconnectLogicalLink:: Exception in callback l2ca_DisconnectInd!\n"));
		}

		gpL2CAP->Lock ();
		pOwner->DelRef ();
		IFDBG(DebugOut (DEBUG_L2CAP_CALLBACK, L"DisconnectLogicalLink:: Back from callback\n"));
	}

	if ((gpL2CAP->eStage == Connected) && fSendDisconnect && (cid_remote != INVALID_CID) && (h != BT_HCI_INVALID_HANDLE)) {
		IFDBG(DebugOut (DEBUG_L2CAP_TRACE, L"Sending disconnect signal\n"));
		Signal s;
		s.cid = 1;
		s.length = sizeof(s.packet.h) + sizeof(s.packet.u.DISCONNECT_REQUEST);
		s.packet.h.code = L2CAP_COMMAND_DISCONNECT_REQUEST;
		s.packet.h.id = gpL2CAP->ucCurrentID++;
		if (! s.packet.h.id)
			s.packet.h.id = gpL2CAP->ucCurrentID++;
		s.packet.h.length = sizeof(s.packet.u.DISCONNECT_REQUEST);
		s.packet.u.DISCONNECT_REQUEST.dest_cid = cid_remote;
		s.packet.u.DISCONNECT_REQUEST.source_cid = cid;

		int iRes = WriteDataDown (h, NULL, SIGNAL_LENGTH(s), (unsigned char *)&s);

		IFDBG(DebugOut (DEBUG_L2CAP_TRACE, L"WriteDataDown returns %d\n", iRes));
	}
}

static int DisconnectPhysicalLink (PhysLink *pPhysLink, int fReconnect, int iErr, CallContext *pCallContext) {
	IFDBG(DebugOut (DEBUG_L2CAP_TRACE, L"DisconnectPhysicalLink :: %04x%08x reconnect = %d\n", pPhysLink->b.NAP, pPhysLink->b.SAP, fReconnect));

	SVSUTIL_ASSERT((! pCallContext) || (! fReconnect));

	UnscheduleTimeout (pPhysLink);

	if ((pPhysLink->iConnectionAttempts > L2CAP_RECONNECT) || (gpL2CAP->eStage == Disconnected))
		fReconnect = FALSE;

	if (! fReconnect)
		PluckPhysLink (pPhysLink);

	while (gpL2CAP->IsStackRunning () && pPhysLink->pLogLinks) {
		SVSUTIL_ASSERT (! pCallContext);
		LogLink *pThis = pPhysLink->pLogLinks;

		if (fReconnect) {
			while (pThis && ((pThis->eStage == STARTING) || (pThis->eStage == STARTING_PHYS)))
				pThis = pThis->pNext;

			if (! pThis)
				break;
		}

		DisconnectLogicalLink (pThis, iErr, FALSE);
	}

	if (! gpL2CAP->IsStackRunning ())
		return ERROR_SHUTDOWN_IN_PROGRESS;

	if (fReconnect && (! pPhysLink->pLogLinks)) {
		fReconnect = FALSE;
		PluckPhysLink (pPhysLink);
	}

	if (! fReconnect) {
		CallContext *pCall;
		while (gpL2CAP->IsStackRunning () && (pCall = FindCall (pPhysLink))) {
			SVSUTIL_ASSERT (! pCallContext);
			AbortCall (pCall, iErr);
		}

		if (gpL2CAP->eStage == Connected) {
			unsigned short h = pPhysLink->h;
			HCI_Disconnect_In pCallback = (pPhysLink->eStage == UP) ? gpL2CAP->hci_if.hci_Disconnect_In : NULL;
			HANDLE hHCI = gpL2CAP->hHCI;
			IFDBG(BD_ADDR b = pPhysLink->b);

			delete pPhysLink;

			if (pCallback) {
				IFDBG(DebugOut (DEBUG_L2CAP_TRACE, L"Taking down connection to %04x%08x handle 0x%04x\n", b.NAP, b.SAP, h));

				IFDBG(DebugOut (DEBUG_L2CAP_CALLBACK, L"Going into hci_Disconnect_In callback\n"));
				gpL2CAP->AddRef ();
				gpL2CAP->Unlock ();

				int iRes = ERROR_INTERNAL_ERROR;
				__try {
					iRes = pCallback (hHCI, pCallContext, h, 0x13);
				} __except (1) {
					IFDBG(DebugOut (DEBUG_ERROR, L"Exception in hci_Disconnect_In\n"));
				}
				gpL2CAP->Lock ();
				gpL2CAP->DelRef ();

				IFDBG(DebugOut (DEBUG_L2CAP_CALLBACK, L"Came from hci_Disconnect_In callback\n"));

				return gpL2CAP->eStage == Connected ? iRes : ERROR_SHUTDOWN_IN_PROGRESS;
			}

			return ERROR_SUCCESS;
		}

		return ERROR_SHUTDOWN_IN_PROGRESS;
	}

	SVSUTIL_ASSERT (! pCallContext);

	++pPhysLink->iConnectionAttempts;

	pPhysLink->eStage = STARTING;
	pPhysLink->h = BT_HCI_INVALID_HANDLE;
	pPhysLink->iPingsSent = 0;
	pPhysLink->iTransmissionProblems = 0;
	pPhysLink->dwTimeOutCookie = 0;

	LogLink *pLog = pPhysLink->pLogLinks;
	while (pLog) {
		SVSUTIL_ASSERT ((pLog->eStage == STARTING) || (pLog->eStage == STARTING_PHYS));
		pLog->cid = 0;
		pLog->eStage = STARTING_PHYS;
		pLog = pLog->pNext;
	}

	BD_ADDR b = pPhysLink->b;
	HANDLE hHCI = gpL2CAP->hHCI;
	HCI_CreateConnection_In pHCICall = gpL2CAP->hci_if.hci_CreateConnection_In;
	unsigned short usPacketType = pPhysLink->usPacketType ? pPhysLink->usPacketType : gpL2CAP->usPacketType;

	BT_LAYER_IO_CONTROL pIoctl = gpL2CAP->hci_if.hci_ioctl;

	int iRes = ERROR_INTERNAL_ERROR;

	CallContext *pCall = FindCall (pPhysLink, CALL_PHYS_CONNECT); // Must!

	if (pCall) {
		IFDBG(DebugOut (DEBUG_HCI_CALLBACK, L"going into in hci_CreateConnection_In\n"));
		gpL2CAP->AddRef ();
		gpL2CAP->Unlock ();
		__try {

⌨️ 快捷键说明

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