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

📄 rfcomm.cxx

📁 三星2440原版bsp
💻 CXX
📖 第 1 页 / 共 5 页
字号:
	}


	if (pSess->kTimeoutCookie) {
		IFDBG(DebugOut (DEBUG_RFCOMM_TRACE, L"TimeoutSession :: closing session %04x%08x\n", pSess->b.NAP, pSess->b.SAP));
		CloseSession (pSess, ERROR_TIMEOUT, TRUE);
	}

	IFDBG(DebugOut (DEBUG_RFCOMM_TRACE, L"TimeoutSession :: ERROR_SUCCESS\n"));
	gpRFCOMM->Unlock ();

	return ERROR_SUCCESS;
}

static void ScheduleTimeout (Session *pSess, int iTimeoutSec) {
	IFDBG(DebugOut (DEBUG_RFCOMM_TRACE, L"ScheduleTimeout %d : %04x%08x\n", iTimeoutSec, pSess->b.NAP, pSess->b.SAP));

	if (pSess->kTimeoutCookie)
		btutil_UnScheduleEvent (pSess->kTimeoutCookie);

	pSess->kTimeoutCookie = btutil_ScheduleEvent (TimeoutSession, pSess, iTimeoutSec * 1000);
}

static void ClearTimeout (Session *pSess) {
	IFDBG(DebugOut (DEBUG_RFCOMM_TRACE, L"ClearTimeout : %04x%08x\n", pSess->b.NAP, pSess->b.SAP));

	if (pSess->kTimeoutCookie)
		btutil_UnScheduleEvent (pSess->kTimeoutCookie);
	pSess->kTimeoutCookie = 0;
}

static void SetBusy (Session *pSess, Task *pCall) {
	IFDBG(DebugOut (DEBUG_RFCOMM_TRACE, L"SetBusy : %04x%08x\n", pSess->b.NAP, pSess->b.SAP));
	SVSUTIL_ASSERT (gpRFCOMM->fConnected);
	SVSUTIL_ASSERT (pCall->pPhysLink == pSess);
	SVSUTIL_ASSERT (! pSess->fWaitAck);

#if defined (DEBUG) || defined (_DEBUG)
	Task *pCall2 = gpRFCOMM->pCalls;
	while (pCall2 && ((pCall2->pPhysLink != pSess) || (! pCall2->fPF)))
		pCall2 = pCall2->pNext;

	SVSUTIL_ASSERT (! pCall2);
#endif

	pSess->fBusy = TRUE;
	pCall->fPF = TRUE;

#if defined (DEBUG) || defined (_DEBUG)
	pSess->ucDbgBusyChannel = pCall->channel;
#endif

	ScheduleTimeout (pSess, RFCOMM_T1);
}

static void ClearBusy (Session *pSess) {
	IFDBG(DebugOut (DEBUG_RFCOMM_TRACE, L"ClearBusy : %04x%08x\n", pSess->b.NAP, pSess->b.SAP));
	SVSUTIL_ASSERT (gpRFCOMM->fConnected);

	pSess->fBusy = FALSE;

#if defined (DEBUG) || defined (_DEBUG)
	pSess->ucDbgBusyChannel = 0;
#endif

	ClearTimeout (pSess);
}

static void GetConnectionState (void) {
	gpRFCOMM->fConnected = FALSE;

	__try {
		int fConnected = FALSE;
		int dwRet = 0;
		gpRFCOMM->l2cap_if.l2ca_ioctl (gpRFCOMM->hL2CAP, BTH_STACK_IOCTL_GET_CONNECTED, 0, NULL, sizeof(fConnected), (char *)&fConnected, &dwRet);
		if ((dwRet == sizeof(fConnected)) && fConnected)
			gpRFCOMM->fConnected = TRUE;
	} __except (1) {
		IFDBG(DebugOut (DEBUG_ERROR, L"[RFCOMM] GetConnectionState : exception in hci_ioctl BTH_STACK_IOCTL_GET_CONNECTED\n"));
	}
}
//
//	DIRECTION bit is set on device making the connection (fIncoming && (! fLocal)) or ((! fIncoming) && fLocal)
//

static inline unsigned char GetDLCI (Task *pCall) {
	if (pCall->channel == 0)
		return 0;

	return (pCall->channel << 1) | ((pCall->pPhysLink->fIncoming && (! pCall->fLocal)) || ((! pCall->pPhysLink->fIncoming) && pCall->fLocal));
}

static inline unsigned char GetDLCI (DLCI *pDLCI) {
	SVSUTIL_ASSERT (pDLCI->pSess->fStage != DORMANT);
	return (pDLCI->channel << 1) | ((pDLCI->pSess->fIncoming && (! pDLCI->fLocal)) || ((! pDLCI->pSess->fIncoming) && pDLCI->fLocal));
}

// If (fIncoming && (! DIRECTION)) || ((! fIncoming) && DIRECTION)
static inline int IsLocal (Session *pSess, unsigned char dlci) {
	SVSUTIL_ASSERT (pSess->fStage != DORMANT);

	return (pSess->fIncoming && ((dlci & 1) == 0)) || ((! pSess->fIncoming) && ((dlci & 1) == 1));
}

static int ProcessNextPendingEvent (Session *pSess) {
	SVSUTIL_ASSERT (VerifyLink (pSess));
	SVSUTIL_ASSERT (! pSess->fBusy);
	SVSUTIL_ASSERT (! pSess->fWaitAck);
	SVSUTIL_ASSERT (pSess->fStage == UP);

	Task *pCall = gpRFCOMM->pCalls;
	while (pCall && ((pCall->pPhysLink != pSess) || pCall->fData))
		pCall = pCall->pNext;

	if (! pCall)
		return ERROR_NOT_FOUND;

	SVSUTIL_ASSERT ((pCall->fWhat == CALL_RFCOMM_SABMN) || (pCall->fWhat == CALL_RFCOMM_DISCN));

	SetBusy (pSess, pCall);

	if (pCall->fWhat == CALL_RFCOMM_SABMN)
		return SendFrame (pCall, pSess->cid, GetDLCI (pCall), pSess->fIncoming, CTL_SABM);
	else if (pCall->fWhat == CALL_RFCOMM_DISCN)
		return SendFrame (pCall, pSess->cid, GetDLCI (pCall), pSess->fIncoming, CTL_DISC);

	SVSUTIL_ASSERT (0);
	return ERROR_INTERNAL_ERROR;
}

static int ProcessPendingSignals (Session *pSess) {
	do {
		Task *pTask = gpRFCOMM->pCalls;
		while (pTask && ((pTask->pPhysLink != pSess) || (! pTask->signal_length)))
			pTask = pTask->pNext;

		if (! pTask)
			break;

		SVSUTIL_ASSERT (pTask->fWhat == CALL_RFCOMM_SIGNALDATA);
		SVSUTIL_ASSERT (pTask->eType == MSG_PN);

		// Verify if n1 has to be changed due to l2cap MTU negotiation
		unsigned short n1 = (unsigned short) (pTask->signal_body[6] | (pTask->signal_body[7] << 8));
		if (n1 > (pSess->outMTU - (sizeof(TS_FRAME_HEADER_X) + sizeof(TS_FRAME_FOOTER)))) {
			n1 = pSess->outMTU - (sizeof(TS_FRAME_HEADER_X) + sizeof(TS_FRAME_FOOTER));
			pTask->signal_body[6] = n1 & 0xff;					// n1 1-8
			pTask->signal_body[7] = (n1 >> 8) & 0xff;			// n1 9-16
		}

		if (pTask->signal_dlci_offset)
			pTask->signal_body[pTask->signal_dlci_offset] = GetDLCI(pTask);

		pTask->signal_dlci_offset = 0;

		int cBytes = pTask->signal_length;
		pTask->signal_length = 0;

		int iRes = SendFrame (pTask, pSess->cid, pSess->fIncoming, cBytes, pTask->signal_body);
		if (iRes != ERROR_SUCCESS)
			return iRes;
	} while (gpRFCOMM->fConnected && VerifyLink (pSess));

	return ERROR_SUCCESS;
}

static int DisconnectPeer (Session *pSess, DLCI *pChan, void *pContext) {
	IFDBG(DebugOut (DEBUG_RFCOMM_TRACE, L"DisconnectPeer : %04x%08x h = 0x%08x\n", pSess->b.NAP, pSess->b.SAP, pChan));
	if (gpRFCOMM->fConnected && (pSess->fStage == UP) && pChan->channel && (pChan->fStage == UP)) {
		Task *pCall = NewTask (CALL_RFCOMM_DISCN, pChan->pOwner, pSess);
		if (pCall) {
			pCall->channel 	= pChan->channel;
			pCall->fLocal  	= pChan->fLocal;
			pCall->pContext	= pContext;

			AddTask (pCall);

			if (! pSess->fBusy)
				ProcessNextPendingEvent (pSess);

			return TRUE;
		}
	}

	return FALSE;
}

static void DeleteChannel (Session *pSess, DLCI *pChan, int iSignal, int iError, void *pCallContext, int fCloseSessOverride = FALSE) {
	IFDBG(DebugOut (DEBUG_RFCOMM_TRACE, L"DeleteChannel : %04x%08x h = 0x%08x close %d err %d\n", pSess->b.NAP, pSess->b.SAP, pChan, iSignal, iError));

	if (! pChan)
   		return;

	SVSUTIL_ASSERT (pChan->pSess == pSess);

	int fstarted = pChan->fStage == UP;
	unsigned char fLocal = pChan->fLocal;
	unsigned char channel = pChan->channel;
	RFCOMM_CONTEXT *pOwner = pChan->pOwner;

	if (pChan == pSess->pLogLinks)
		pSess->pLogLinks = pSess->pLogLinks->pNext;
	else {
		DLCI *pP = pSess->pLogLinks;
		while (pP && (pP->pNext != pChan))
			pP = pP->pNext;
		if (pP)
			pP->pNext = pP->pNext->pNext;
		else
			pChan = NULL;
	}

	// Close the session, but only cancel outstanding calls if we are not going to call up to
	// a disconnect function.
	BOOL fCancelCalls = ! (gpRFCOMM->fConnected && VerifyContext (pOwner));
	if ((! pSess->pLogLinks) && (! fCloseSessOverride))
		CloseSession (pSess, iError, fCancelCalls);

    if (gpRFCOMM->fConnected && VerifyContext (pOwner)) {
		if ((iSignal == RFCOMM_SIGNAL_ASYNC) && fstarted) {
			RFCOMM_Disconnect_Ind pCallback = pOwner->ei.rfcomm_Disconnect_Ind;
			void *pUserContext = pOwner->pUserContext;

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

			IFDBG(DebugOut (DEBUG_RFCOMM_CALLBACK, L"DeleteChannel : going into rfcomm_Disconnect_Ind\n"));

			__try {
				pCallback (pUserContext, pChan);
			} __except (1) {
				IFDBG(DebugOut (DEBUG_ERROR, L"[RFCOMM] DeleteChannel : Exception in rfcomm_Disconnect_Ind\n"));
			}

			gpRFCOMM->Lock ();
			pOwner->DelRef ();

			IFDBG(DebugOut (DEBUG_RFCOMM_CALLBACK, L"DeleteChannel : out of rfcomm_Disconnect_Ind\n"));
		} else if (iSignal == RFCOMM_SIGNAL_RESPONSE) {
			RFCOMM_Disconnect_Out pCallback = pOwner->c.rfcomm_Disconnect_Out;

			if (pCallback) {
				pOwner->AddRef ();
				gpRFCOMM->Unlock ();

				IFDBG(DebugOut (DEBUG_RFCOMM_CALLBACK, L"DeleteChannel : going into rfcomm_Disconnect_Out\n"));

				__try {
					pCallback (pCallContext, iError);
				} __except (1) {
					IFDBG(DebugOut (DEBUG_ERROR, L"[RFCOMM] DeleteChannel : Exception in rfcomm_Disconnect_Out\n"));
				}

				gpRFCOMM->Lock ();
				pOwner->DelRef ();
			}

			IFDBG(DebugOut (DEBUG_RFCOMM_CALLBACK, L"DeleteChannel : out of rfcomm_Disconnect_Out\n"));
		}
    }

	if (gpRFCOMM->fRunning)
		delete pChan;
}

static void CloseSession (Session *pSess, int iError, BOOL fCancelCalls) {
	IFDBG(DebugOut (DEBUG_RFCOMM_TRACE, L"CloseSession : 0x%08x\n", pSess));

	if (pSess == gpRFCOMM->pPhysLinks)
		gpRFCOMM->pPhysLinks = gpRFCOMM->pPhysLinks->pNext;
	else {
		Session *pP = gpRFCOMM->pPhysLinks;
		while (pP && (pP->pNext != pSess))
			pP = pP->pNext;

		if (pP)
			pP->pNext = pP->pNext->pNext;
		else
			pSess = NULL;
	}

	unsigned short cid = INVALID_CID;

	if (pSess) {	// Get rid of channels
		IFDBG(DebugOut (DEBUG_RFCOMM_TRACE, L"CloseSession:: closing %04x%08x\n", pSess->b.NAP, pSess->b.SAP));
		while (pSess->pLogLinks && gpRFCOMM->fRunning)
			DeleteChannel (pSess, pSess->pLogLinks, RFCOMM_SIGNAL_ASYNC, iError, NULL);

		ClearTimeout (pSess);

		if (gpRFCOMM->fConnected)
			cid = pSess->cid;
	} else
		IFDBG(DebugOut (DEBUG_WARN, L"CloseSession:: Session 0x%08x not found!\n", pSess));

	Task *pCall = gpRFCOMM->pCalls;
	while (pCall) {
		if (pCall->pPhysLink == pSess) {
			if (fCancelCalls)
				CancelCall (pCall, iError, NULL);
			else
				DeleteCall (pCall);
			if (! gpRFCOMM->fConnected) {
				cid = INVALID_CID;
				break;
			}

			pCall = gpRFCOMM->pCalls;
		} else
			pCall = pCall->pNext;
	}

	if (pSess && gpRFCOMM->fRunning)
		delete pSess;

	if (cid != INVALID_CID) {	// Close CID
		SVSUTIL_ASSERT (pSess->fStage >= CONNECTED);

		HANDLE h = gpRFCOMM->hL2CAP;

		L2CA_Disconnect_In pCallback = gpRFCOMM->l2cap_if.l2ca_Disconnect_In;
		gpRFCOMM->AddRef ();
		gpRFCOMM->Unlock ();

		IFDBG(DebugOut (DEBUG_RFCOMM_CALLBACK, L"CloseSession : going into l2ca_Disconnect_In\n"));

		__try {
			pCallback (h, NULL, cid);
		} __except (1) {
			IFDBG(DebugOut (DEBUG_ERROR, L"[RFCOMM] CloseSession :: Exception in l2ca_Disconnect_In\n"));
		}
		gpRFCOMM->Lock ();
		gpRFCOMM->DelRef ();

		IFDBG(DebugOut (DEBUG_RFCOMM_CALLBACK, L"CloseSession : came out of l2ca_Disconnect_In\n"));
	}
}

static void IncrHWErr (Session *pSess) {
	IFDBG(DebugOut (DEBUG_WARN, L"[RFCOMM] IncrHWErr : %04x%08x (to %d)\n", pSess->b.NAP, pSess->b.SAP, pSess->iErr + 1));

	pSess->iErr++;
	if (pSess->iErr > RFCOMM_MAX_ERR) {
		IFDBG(DebugOut (DEBUG_ERROR, L"[RFCOMM] Session to %04x%08x closed because of hardware errors (%d total)\n",
			pSess->b.NAP, pSess->b.SAP, pSess->iErr));

		CloseSession (pSess, ERROR_INVALID_DATA, TRUE);
	}
}

//
//	Communicate stack event up
//
static void DispatchStackEvent (int iEvent) {
	RFCOMM_CONTEXT *pContext = gpRFCOMM->pContexts;
	while (pContext && gpRFCOMM->fRunning) {
		BT_LAYER_STACK_EVENT_IND pCallback = pContext->ei.rfcomm_StackEvent;
		if (pCallback) {
			void *pUserContext = pContext->pUserContext;

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

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

			gpRFCOMM->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_RFCOMM_TRACE, L"Disconnect stack\n"));

	for ( ; ; ) {
		if (! gpRFCOMM) {
			IFDBG(DebugOut (DEBUG_ERROR, L"StackDown : ERROR_SERVICE_DOES_NOT_EXIST\n"));
			return ERROR_SERVICE_DOES_NOT_EXIST;
		}

		gpRFCOMM->Lock ();

		if ((! gpRFCOMM->fConnected)  || (! gpRFCOMM->fRunning)) {
			IFDBG(DebugOut (DEBUG_ERROR, L"StackDown : ERROR_SERVICE_NOT_ACTIVE\n"));
			gpRFCOMM->Unlock ();
			return ERROR_SERVICE_NOT_ACTIVE;
		}

		if (gpRFCOMM->GetRefCount () == 1)
			break;

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

	gpRFCOMM->AddRef ();

	gpRFCOMM->fConnected = FALSE;

	while (gpRFCOMM->pPhysLinks && gpRFCOMM->fRunning)
		CloseSession (gpRFCOMM->pPhysLinks, ERROR_SHUTDOWN_IN_PROGRESS, TRUE);

	while (gpRFCOMM->pCalls && gpRFCOMM->fRunning)
		CancelCall (gpRFCOMM->pCalls, ERROR_SHUTDOWN_IN_PROGRESS, NULL);

	DispatchStackEvent (BTH_STACK_DOWN);

	gpRFCOMM->DelRef ();

	IFDBG(DebugOut (DEBUG_RFCOMM_TRACE, L"-StackDown\n"));
	gpRFCOMM->Unlock ();

	return ERROR_SUCCESS;
}

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

	for ( ; ; ) {
		if (! gpRFCOMM) {
			IFDBG(DebugOut (DEBUG_ERROR, L"StackUp : ERROR_SERVICE_DOES_NOT_EXIST\n"));
			return ERROR_SERVICE_DOES_NOT_EXIST;
		}

		gpRFCOMM->Lock ();

		if (gpRFCOMM->fConnected || (! gpRFCOMM->fRunning)) {
			IFDBG(DebugOut (DEBUG_ERROR, L"StackUp : ERROR_SERVICE_NOT_ACTIVE\n"));
			gpRFCOMM->Unlock ();
			return ERROR_SERVICE_NOT_ACTIVE;

⌨️ 快捷键说明

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