📄 rfcomm.cxx
字号:
int cDataTrailers; // Size of headers at the upper layer
DWORD dwLinger; // Lingering timeout
unsigned int fRunning : 1; // Running?
unsigned int fConnected : 1; // Device connected?
void ReInit (void) {
pContexts = NULL;
pPhysLinks = NULL;
pCalls = NULL;
pfmdSessions = NULL;
pfmdChannels = NULL;
pfmdCalls = NULL;
pfmdSC = NULL;
hL2CAP = NULL;
memset (&l2cap_if, 0, sizeof(l2cap_if));
cDataHeaders = 0;
cDataTrailers = 0;
dwLinger = 0;
fRunning = FALSE;
fConnected = FALSE;
}
RFCOMM (void) {
ReInit ();
}
};
static RFCOMM *gpRFCOMM = NULL;
// Adapted from the ETSI specification:
// (GSM 07.10 version 6.3.0 Release 1997)
static const unsigned char crctable[256] = { //reversed, 8-bit, poly=0x07
0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B,
0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67,
0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43,
0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F,
0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B,
0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17,
0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33,
0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F,
0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B,
0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87,
0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3,
0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF,
0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB,
0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7,
0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3,
0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF
};
static unsigned char FCSCompute(unsigned char *p, int len)
{
/*Init*/
unsigned char fcs = 0xFF;
/*len is the number of bytes in the message, p points to message*/
while (len--) {
fcs = crctable[fcs^*p++];
}
/*Ones complement*/
fcs = 0xFF - fcs;
return fcs;
}
// Returns TRUE if indicated FCS is valid
static int FCSValidate(unsigned char *p, int len, unsigned char ReceivedFCS)
{
/*Init*/
unsigned char fcs = 0xFF;
/*len is the number of bytes in the message, p points to message*/
while (len--)
fcs = crctable[fcs^*p++];
/*Ones complement*/
fcs = crctable[fcs^ReceivedFCS];
/*0xCF is the reversed order of 11110011.*/
return fcs == 0xCF;
}
static RFCOMM_CONTEXT *VerifyOwner (RFCOMM_CONTEXT *pOwner) {
RFCOMM_CONTEXT *pCtx = gpRFCOMM->pContexts;
while (pCtx && (pCtx != pOwner))
pCtx = pCtx->pNext;
return pCtx;
}
static Task *VerifyCall (Task *pCall) {
Task *pC = gpRFCOMM->pCalls;
while (pC && (pC != pCall))
pC = pC->pNext;
return pC;
}
static Session *VerifyLink (Session *pSess) {
Session *pS = gpRFCOMM->pPhysLinks;
while (pS && (pS != pSess))
pS = pS->pNext;
return pS;
}
static DLCI *VerifyChannel (Session *pSess, DLCI *pChann) {
DLCI *p = pSess->pLogLinks;
while (p && (p != pChann))
p = p->pNext;
return p;
}
static RFCOMM_CONTEXT *VerifyContext (RFCOMM_CONTEXT *pContext) {
RFCOMM_CONTEXT *pC = gpRFCOMM->pContexts;
while (pC && (pC != pContext))
pC = pC->pNext;
return pC;
}
static RFCOMM_CONTEXT *FindContextByChannel (unsigned char ch) {
RFCOMM_CONTEXT *pContext = gpRFCOMM->pContexts;
while (pContext) {
ServerChannel *pSC = pContext->pReservedChannels;
while (pSC) {
if (pSC->channel == ch)
return pContext;
pSC = pSC->pNext;
}
pContext = pContext->pNext;
}
return NULL;
}
static RFCOMM_CONTEXT *FindContextForDefault (void) {
RFCOMM_CONTEXT *pContext = gpRFCOMM->pContexts;
while (pContext) {
if (pContext->fDefaultServer)
return pContext;
pContext = pContext->pNext;
}
return NULL;
}
static DLCI *HandleToDLCI (HANDLE hConnection, RFCOMM_CONTEXT *pOwner) {
if (! hConnection)
return NULL;
DLCI *pDLCI = (DLCI *)hConnection;
Session *pSess = NULL;
__try {
pSess = pDLCI->pSess;
} __except (1) {
pSess = NULL;
}
if (! pSess)
return NULL;
Session *pS = gpRFCOMM->pPhysLinks;
while (pS && (pS != pSess))
pS = pS->pNext;
if (! pS)
return NULL;
DLCI *pD = pS->pLogLinks;
while (pD && ((pD != pDLCI) || (pD->pOwner != pOwner)))
pD = pD->pNext;
return pD;
}
static Task *NewTask (int fWhat, RFCOMM_CONTEXT *pOwner, Session *pSess) { return new Task (fWhat, pOwner, pSess); }
static Task *NewTask (RFCOMM_CONTEXT *a_pOwner, Session *a_pSess, void *a_pContext, unsigned char a_cType) {
return new Task (a_pOwner, a_pSess, a_pContext, a_cType);
}
static Session *NewSession (BD_ADDR *pba) { return new Session (pba); }
static DLCI *NewLog (Session *pSess, unsigned char channel, unsigned int fLocal, RFCOMM_CONTEXT *pOwner) { return new DLCI (pSess, channel, fLocal, pOwner); }
static void AddTask (Task *pTask) {
SVSUTIL_ASSERT (pTask->pNext == NULL);
if (! gpRFCOMM->pCalls)
gpRFCOMM->pCalls = pTask;
else {
Task *pParent = gpRFCOMM->pCalls;
while (pParent->pNext)
pParent = pParent->pNext;
pParent->pNext = pTask;
}
}
static void DeleteCall (Task *pTask) {
if (pTask == gpRFCOMM->pCalls)
gpRFCOMM->pCalls = gpRFCOMM->pCalls->pNext;
else {
Task *pP = gpRFCOMM->pCalls;
while (pP && (pP->pNext != pTask))
pP = pP->pNext;
if (pP)
pP->pNext = pP->pNext->pNext;
else
pTask = NULL;
}
if (pTask)
delete pTask;
return;
}
static void CancelCall (Task *pCall, int iError, RFCOMM_CONTEXT *pExOwner) {
void *pUserContext = pCall->pContext;
RFCOMM_CONTEXT *pOwner = pCall->pOwner;
SVSUTIL_ASSERT ((! pOwner) || VerifyOwner (pOwner));
DeleteCall (pCall);
if (! pOwner)
pOwner = pExOwner;
if (! pOwner)
return;
BT_LAYER_CALL_ABORTED pCallback = pOwner->c.rfcomm_CallAborted;
pOwner->AddRef ();
gpRFCOMM->Unlock ();
IFDBG(DebugOut (DEBUG_RFCOMM_CALLBACK, L"CancelCall : going into rfcomm_CallAborted\n"));
__try {
pCallback (pUserContext, iError);
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"[RFCOMM] CancelCall :: exception in rfcomm_CallAborted\n"));
}
gpRFCOMM->Lock ();
pOwner->DelRef ();
IFDBG(DebugOut (DEBUG_RFCOMM_CALLBACK, L"CancelCall : came out of rfcomm_CallAborted\n"));
}
static int SendFrame (Task *pTask, unsigned short cid, BD_BUFFER *pb) {
IFDBG(DebugOut (DEBUG_RFCOMM_PACKETS, L"SendFrame :: cid = 0x%04x %d bytes\n", cid, pb->cEnd - pb->cStart));
SVSUTIL_ASSERT (gpRFCOMM->fConnected);
HANDLE h = gpRFCOMM->hL2CAP;
L2CA_DataDown_In pCallback = gpRFCOMM->l2cap_if.l2ca_DataDown_In;
int iRes = ERROR_INTERNAL_ERROR;
gpRFCOMM->AddRef ();
gpRFCOMM->Unlock ();
IFDBG(DebugOut (DEBUG_RFCOMM_CALLBACK, L"SendFrame : going into l2ca_DataDown_In\n"));
__try {
iRes = pCallback (h, pTask, cid, pb);
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"[RFCOMM] SendFrame :: exception in l2ca_DataDown_In!\n"));
}
gpRFCOMM->Lock ();
gpRFCOMM->DelRef ();
IFDBG(DebugOut (DEBUG_RFCOMM_CALLBACK, L"SendFrame : came out of l2ca_DataDown_In\n"));
IFDBG(DebugOut (DEBUG_RFCOMM_TRACE, L"SendFrame returns %d\n", iRes));
return iRes;
}
static int SendFrame (Task *pTask, unsigned short cid, int fIncoming, int cBytes, unsigned char *pBytes) {
#if defined (DEBUG) || defined (_DEBUG)
WCHAR *szCMD = L"UNKN";
WCHAR *szQual = L"";
if (cBytes > 0) {
if ((*pBytes & CR_BIT) == 0)
szQual = L"-Resp";
switch (*pBytes >> 2) {
case MSG_TEST:
szCMD = L"MSG_TEST";
break;
case MSG_FCON:
szCMD = L"MSG_FCON";
break;
case MSG_FCOFF:
szCMD = L"MSG_FCOFF";
break;
case MSG_MSC:
szCMD = L"MSG_MSC";
break;
case MSG_RPN:
szCMD = L"MSG_RPN";
break;
case MSG_RLS:
szCMD = L"MSG_RLS";
break;
case MSG_PN:
szCMD = L"MSG_PN";
break;
case MSG_NSC:
szCMD = L"MSG_NSC";
break;
case MSG_PSC:
szCMD = L"MSG_PSC";
break;
case MSG_CLD:
szCMD = L"MSG_CLD";
break;
case MSG_SNC:
szCMD = L"MSG_SNC";
break;
}
}
IFDBG(DebugOut (DEBUG_RFCOMM_PACKETS, L"SendFrame <%s%s> :: cid = 0x%04x %d bytes\n", szCMD, szQual, cid, cBytes));
#endif
SVSUTIL_ASSERT (cBytes <= 127);
SVSUTIL_ASSERT (cBytes > 0);
int cFrameSize = gpRFCOMM->cDataHeaders + sizeof(TS_FRAME_HEADER) + cBytes + sizeof(TS_FRAME_FOOTER) + gpRFCOMM->cDataTrailers;
BD_BUFFER *pBuffer = BufferAlloc (cFrameSize);
if (! pBuffer)
return ERROR_OUTOFMEMORY;
pBuffer->cStart = gpRFCOMM->cDataHeaders;
pBuffer->cEnd = pBuffer->cSize - gpRFCOMM->cDataTrailers - 1;
TS_FRAME_HEADER *pHeader = (TS_FRAME_HEADER *)&pBuffer->pBuffer[pBuffer->cStart];
pHeader->ucAddress = EA_BIT | (fIncoming ? 0 : CR_BIT) | 0;
pHeader->ucControl = CTL_UIH;
pHeader->ucLength = (unsigned char) (cBytes << 1);
pHeader->ucLength |= EA_BIT;
memcpy (pHeader + 1, pBytes, cBytes);
pBuffer->pBuffer[pBuffer->cEnd++] = FCSCompute (pBuffer->pBuffer + pBuffer->cStart, 2);
return SendFrame (pTask, cid, pBuffer);
}
static int SendFrame (Task *pTask, unsigned short cid, int dlci, int fIncoming, int cframe) {
IFDBG(DebugOut (DEBUG_RFCOMM_PACKETS, L"SendFrame :: cid = 0x%04x channel = %d frame = %s\n", cid, dlci >> 1,
cframe == CTL_DISC ? L"DISC" : (cframe == CTL_SABM ? L"SABM" : (cframe == CTL_UA ? L"UA" : L"DM"))));
SVSUTIL_ASSERT ((cframe == CTL_DISC) || (cframe == CTL_SABM) || (cframe == CTL_UA) || (cframe == CTL_DM));
BD_BUFFER b;
b.cSize = gpRFCOMM->cDataHeaders + gpRFCOMM->cDataTrailers + sizeof(TS_FRAME);
b.cStart = gpRFCOMM->cDataHeaders;
b.cEnd = b.cStart + sizeof(TS_FRAME);
b.fMustCopy = TRUE;
b.pFree = NULL;
b.pBuffer = (unsigned char *)_alloca (b.cSize);
TS_FRAME *pDiscFrame = (TS_FRAME *)(b.pBuffer + b.cStart);
pDiscFrame->h.ucAddress = EA_BIT | (dlci << 2);
// CR bit set for command responses for responder and for command requests for initiator
if (fIncoming) {
if ((cframe == CTL_UA) || (cframe == CTL_DM))
pDiscFrame->h.ucAddress |= CR_BIT;
} else {
if ((cframe == CTL_DISC) || (cframe == CTL_SABM)) //command
pDiscFrame->h.ucAddress |= CR_BIT;
}
pDiscFrame->h.ucControl = cframe | CTL_PF;
pDiscFrame->h.ucLength = EA_BIT;
pDiscFrame->f.ucFcs = FCSCompute ((unsigned char *)&pDiscFrame->h, sizeof(pDiscFrame->h));
return SendFrame (pTask, cid, &b);
}
static inline int RejectFrame (Session *pSess, TS_FRAME *pF) {
IFDBG(DebugOut (DEBUG_WARN, L"[RFCOMM] Frame ctl 0x%02 addr 0x%02 sess %04x%08x rejected\n", pF->h.ucControl, pF->h.ucAddress, pSess->b.NAP, pSess->b.SAP));
return SendFrame (NULL, pSess->cid, pF->h.ucAddress >> 2, pSess->fIncoming, CTL_DM);
}
static inline int AcceptFrame (Session *pSess, TS_FRAME *pF) {
IFDBG(DebugOut (DEBUG_RFCOMM_TRACE, L"Frame ctl 0x%02 addr 0x%02 sess %04x%08x accepted\n", pF->h.ucControl, pF->h.ucAddress, pSess->b.NAP, pSess->b.SAP));
return SendFrame (NULL, pSess->cid, pF->h.ucAddress >> 2, pSess->fIncoming, CTL_UA);
}
static void CloseSession (Session *pSess, int iError, BOOL fCancelCalls);
static DWORD WINAPI TimeoutSession (LPVOID pArg) {
IFDBG(DebugOut (DEBUG_RFCOMM_TRACE, L"TimeoutSession : 0x%08x\n", pArg));
if (! gpRFCOMM) {
IFDBG(DebugOut (DEBUG_ERROR, L"TimeoutSession : system shutdown\n"));
return ERROR_SERVICE_NOT_ACTIVE;
}
gpRFCOMM->Lock ();
if (! gpRFCOMM->fConnected) {
IFDBG(DebugOut (DEBUG_ERROR, L"TimeoutSession : system disconnected\n"));
gpRFCOMM->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
Session *pSess = VerifyLink ((Session *)pArg);
if (! pSess) {
IFDBG(DebugOut (DEBUG_ERROR, L"TimeoutSession : not found\n"));
gpRFCOMM->Unlock ();
return ERROR_NOT_FOUND;
}
if (((Session *)pArg)->pLogLinks) {
IFDBG(DebugOut (DEBUG_RFCOMM_TRACE, L"TimeoutSession : There are still logical links, do not delete session"));
gpRFCOMM->Unlock ();
return ERROR_SUCCESS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -