📄 rfcomm.cxx
字号:
}
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 + -