📄 l2capdev.cxx
字号:
gpState->Unlock ();
L2CAPClosePSM (psm);
if (! gpState)
return;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return;
}
pPort = gpState->pPorts;
continue;
}
pPort = pPort->pNext;
}
Link *pLink = gpState->pLinks;
while (pLink) {
if (pLink->hProcOwner == hProc) {
unsigned short cid = pLink->cid;
gpState->Unlock ();
L2CAPCloseCID (cid);
if (! gpState)
return;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return;
}
pLink = gpState->pLinks;
continue;
}
pLink = pLink->pNext;
}
SCall *pCall = gpState->pCalls;
while (pCall) {
if ((pCall->hProcOwner == hProc) && (! pCall->fComplete)) {
if (pCall->fAutoClean) {
SCall *pNext = pCall->pNext;
DeleteCall (pCall);
pCall = pNext;
continue;
}
pCall->fComplete = TRUE;
pCall->iResult = ERROR_SHUTDOWN_IN_PROGRESS;
SetEvent (pCall->hEvent);
}
pCall = pCall->pNext;
}
gpState->Unlock ();
}
//
// L2CAP stuff
//
static int l2capdev_DataUpInd (void *pUserContext, unsigned short cid, BD_BUFFER *pBuffer) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: Data up on channel 0x%04x %d bytes\n", cid, BufferTotal (pBuffer)));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
Link *pLink = FindLink (cid);
if (pLink) {
SCall *pCall = gpState->pCalls;
while (pCall && ((pCall->pLink != pLink) || (pCall->fWhat != CALL_L2CAP_DATA_READ) || pCall->fComplete))
pCall = pCall->pNext;
if (! pCall) {
pCall = AllocCall (CALL_L2CAP_DATA_READ, pLink, pLink->hProcOwner);
if (! pCall) {
gpState->Unlock ();
return ERROR_OUTOFMEMORY;
}
pCall->fAutoClean = TRUE;
}
pCall->pBuffer = pBuffer->fMustCopy ? L2CAP_BufferCopy (pBuffer) : pBuffer;
pCall->fComplete = TRUE;
pCall->iResult = ERROR_SUCCESS;
SetEvent (pCall->hEvent);
}
gpState->Unlock ();
return ERROR_SUCCESS;
}
static int l2capdev_DisconnectInd (void *pUserContext, unsigned short cid, int iError) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: Disconnect indicator on channel 0x%04x\n", cid));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
Link *pLink = FindLink (cid);
if (! pLink) {
gpState->Unlock ();
return ERROR_NOT_FOUND;
}
if (pLink->fStage == UP) {
SCall *pC = gpState->pCalls;
while (pC) {
if (pC->pLink == pLink) {
if (pC->fAutoClean) {
DeleteCall (pC);
pC = gpState->pCalls;
continue;
} else if (! pC->fComplete) {
pC->fComplete = TRUE;
pC->iResult = ERROR_CONNECTION_UNAVAIL;
SetEvent (pC->hEvent);
}
}
pC = pC->pNext;
}
pLink->fStage |= LINK_ERROR;
} else
DeleteLink (pLink);
gpState->Unlock ();
return ERROR_SUCCESS;
}
static int l2capdev_lStackEvent (void *pUserContext, int iEvent, void *pEventContext) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: Stack event (L2CAP) %d\n", iEvent));
if (! gpState)
return ERROR_SUCCESS;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SUCCESS;
}
LPTHREAD_START_ROUTINE p = NULL;
if (iEvent == BTH_STACK_DISCONNECT)
l2capdev_CloseDriverInstance ();
else if (iEvent == BTH_STACK_DOWN)
p = StackDown;
else if (iEvent == BTH_STACK_UP)
p = StackUp;
HANDLE h = p ? CreateThread (NULL, 0, p, NULL, 0, NULL) : NULL;
if (h) {
CloseHandle (h);
gpState->AddRef ();
}
gpState->Unlock ();
return ERROR_SUCCESS;
}
static int l2capdev_lCallAborted (void *pCallContext, int iError) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: Aborted call 0x%08x error %d\n", pCallContext, iError));
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) {
gpState->Unlock ();
return ERROR_NOT_FOUND;
}
SVSUTIL_ASSERT (! pCall->fComplete);
SVSUTIL_ASSERT (! pCall->pBuffer);
Link *pLink = pCall->pLink;
if (pCall->fAutoClean)
DeleteCall (pCall);
else {
pCall->iResult = iError;
pCall->fComplete = TRUE;
pCall->pLink = NULL;
SetEvent (pCall->hEvent);
}
unsigned short disconnect_cid = 0;
if (pLink) {
if ((pLink->fStage & UP) != UP) {
if (pLink->fStage & CONNECTED)
disconnect_cid = pLink->cid;
else
DeleteLink (pLink);
} else
pLink->fStage |= LINK_ERROR;
}
gpState->Unlock ();
if (disconnect_cid)
L2CAPCloseCID (disconnect_cid);
return ERROR_SUCCESS;
}
static int l2capdev_ConfigInd (void *pUserContext, unsigned char id, unsigned short cid, unsigned short usOutMTU, unsigned short usInFlushTO, struct btFLOWSPEC *pInFlow, int cOptNum, struct btCONFIGEXTENSION **pExtendedOptions) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: Config request indicator on ch 0x%04x id %d MTU %d flush 0x%04x, flow: %s\n", cid, id, usOutMTU, usInFlushTO, pInFlow ? L"yes" : L"no"));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
Link *pLink = FindLink (cid);
SCall *pCall = pLink ? FindCall (pLink, CALL_L2CAP_LINK_SETUP) : NULL;
if ((! pCall) || pCall->fComplete) {
gpState->Unlock ();
return ERROR_NOT_FOUND;
}
SVSUTIL_ASSERT (pCall->fWhat == CALL_L2CAP_LINK_SETUP);
SVSUTIL_ASSERT (! pCall->fComplete);
SVSUTIL_ASSERT (VerifyLink (pCall->pLink));
SVSUTIL_ASSERT (! pCall->pBuffer);
int fAccept = FALSE;
if ((usInFlushTO == 0xffff) && (! pInFlow)) {
pCall->iResult = ERROR_SUCCESS;
pCall->pLink->fStage |= CONFIG_IND_DONE;
pCall->pLink->outMTU = usOutMTU;
fAccept = TRUE;
if (pLink->fStage == UP) {
if (pLink->fIncoming) {
SVSUTIL_ASSERT (pCall->fAutoClean);
pCall->fComplete = TRUE;
SCall *pCall2 = gpState->pCalls;
while (pCall2 && (pCall2->fComplete || (pCall2->fWhat != CALL_L2CAP_ACCEPT) || (pCall2->psm != pLink->psm)))
pCall2 = pCall2->pNext;
if (pCall2) {
DeleteCall (pCall);
pCall2->fComplete = TRUE;
pCall2->iResult = ERROR_SUCCESS;
pCall2->pLink = pLink;
SetEvent (pCall2->hEvent);
}
} else {
pCall->fComplete = TRUE;
pCall->iResult = ERROR_SUCCESS;
SetEvent (pCall->hEvent);
}
}
}
HANDLE hL2CAP = gpState->hL2CAP;
L2CA_ConfigResponse_In pCallback = gpState->l2cap_if.l2ca_ConfigResponse_In;
gpState->Unlock ();
__try {
pCallback (hL2CAP, NULL, id, cid, fAccept ? 0 : 2, 0, 0xffff, NULL, 0, NULL);
} __except (1) {
}
if (! fAccept)
l2capdev_lCallAborted (pCall, ERROR_CONNECTION_ABORTED);
return ERROR_SUCCESS;
}
static int l2capdev_ConfigReq_Out (void *pCallContext, unsigned short usResult, unsigned short usInMTU, unsigned short usOutFlushTO, struct btFLOWSPEC *pOutFlow, int cOptNum, struct btCONFIGEXTENSION **pExtendedOptions) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: Config req out for call 0x%08x result 0x%04x mtu %d flush 0x%04x, flow %s\n", pCallContext, usResult, usInMTU, usOutFlushTO, pOutFlow ? L"yes" : L"no" ));
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_LINK_SETUP);
SVSUTIL_ASSERT (! pCall->fComplete);
SVSUTIL_ASSERT (VerifyLink (pCall->pLink));
SVSUTIL_ASSERT (! pCall->pBuffer);
if (usResult == 0) {
Link *pLink = pCall->pLink;
SVSUTIL_ASSERT (! (pLink->fStage & CONFIG_REQ_DONE));
SVSUTIL_ASSERT (pLink->fStage & CONNECTED);
SVSUTIL_ASSERT (pLink->cid);
SVSUTIL_ASSERT (pLink->psm);
SVSUTIL_ASSERT (pLink->hProcOwner);
pLink->fStage |= CONFIG_REQ_DONE;
if (pLink->fStage == UP) {
if (pLink->fIncoming) {
SVSUTIL_ASSERT (pCall->fAutoClean);
pCall->fComplete = TRUE;
SCall *pCall2 = gpState->pCalls;
while (pCall2 && (pCall2->fComplete || (pCall2->fWhat != CALL_L2CAP_ACCEPT) || (pCall2->psm != pLink->psm)))
pCall2 = pCall2->pNext;
if (pCall2) {
DeleteCall (pCall);
pCall2->fComplete = TRUE;
pCall2->iResult = ERROR_SUCCESS;
pCall2->pLink = pLink;
SetEvent (pCall2->hEvent);
}
} else {
pCall->fComplete = TRUE;
pCall->iResult = ERROR_SUCCESS;
SetEvent (pCall->hEvent);
}
}
gpState->Unlock ();
return ERROR_SUCCESS;
}
gpState->Unlock ();
l2capdev_lCallAborted (pCallContext, ERROR_CONNECTION_ABORTED);
return ERROR_SUCCESS;
}
static int l2capdev_ConnectInd (void *pUserContext, BD_ADDR *pba, unsigned short cid, unsigned char id, unsigned short psm) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: Connect indicator from %04x%08x ch 0x%04x id %d psm 0x%04x\n", pba->NAP, pba->SAP, cid, id, psm));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
Port *pPort = gpState->pPorts;
while (pPort && (pPort->psm != psm))
pPort = pPort->pNext;
unsigned short result;
unsigned short status = 0;
unsigned short mtu = 0;
SCall *pCall = NULL;
if (pPort) {
Link *pLink = (Link *)svsutil_GetFixed (gpState->pfmdLinks);
pCall = pLink ? AllocCall (CALL_L2CAP_LINK_SETUP, pLink, pPort->hProcOwner) : NULL;
if (pCall) {
pCall->fAutoClean = TRUE;
pLink->b = *pba;
pLink->cid = cid;
pLink->fStage = CONNECTED;
pLink->hProcOwner = pPort->hProcOwner;
pLink->inMTU = pPort->mtu;
pLink->outMTU = 0;
pLink->psm = psm;
pLink->fIncoming = TRUE;
pLink->pNext = gpState->pLinks;
gpState->pLinks = pLink;
result = 0;
mtu = pPort->mtu;
} else {
if (pLink)
svsutil_FreeFixed (pLink, gpState->pfmdLinks);
result = 4;
}
} else
result = 2;
HANDLE hL2CAP = gpState->hL2CAP;
L2CA_ConnectResponse_In pCallbackConnect = gpState->l2cap_if.l2ca_ConnectResponse_In;
L2CA_ConfigReq_In pCallbackConfig = gpState->l2cap_if.l2ca_ConfigReq_In;
gpState->Unlock ();
__try {
pCallbackConnect (hL2CAP, NULL, pba, id, cid, result, status);
} __except (1) {
}
if (result == 0) {
int iRes = ERROR_INTERNAL_ERROR;
__try {
iRes = pCallbackConfig (hL2CAP, pCall, cid, mtu, 0xffff, NULL, 0, NULL);
} __except (1) {
}
if (iRes != ERROR_SUCCESS)
l2capdev_lCallAborted (pCall, iRes);
}
return ERROR_SUCCESS;
}
static int l2capdev_ConnectReq_Out (void *pCallContext, unsigned short cid, unsigned short result, unsigned short status) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: Connect out for call 0x%08x ch 0x%04x result = 0x%04x status 0x%04x\n", pCallContext, cid, result, status));
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_LINK_SETUP);
SVSUTIL_ASSERT (! pCall->fComplete);
SVSUTIL_ASSERT (VerifyLink (pCall->pLink));
SVSUTIL_ASSERT (! pCall->pBuffer);
if (result) {
if (result != 1) {
pCall->fComplete = TRUE;
pCall->iResult = ERROR_CONNECTION_REFUSED;
SetEvent (pCall->hEvent);
}
gpState->Unlock ();
return ERROR_SUCCESS;
}
Link *pLink = pCall->pLink;
SVSUTIL_ASSERT (pLink->fStage == NONE);
SVSUTIL_ASSERT (! pLink->cid);
SVSUTIL_ASSERT (pLink->psm);
SVSUTIL_ASSERT (pLink->hProcOwner);
pLink->fStage = CONNECTED;
pLink->cid = cid;
unsigned short mtu = pLink->inMTU;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -